繁体   English   中英

如何按数字和字母值对 swift 中的字符串数组进行排序?

[英]How to sort a string array in swift by number and letter values?

我正在尝试对这样列出的数组进行排序:

let array = ["02:00 AM", "01:00 AM", "01:00 PM", "01:01 AM", "01:01 PM", "03:00 AM"]

这是我可以在我的 userDefaults 中添加/更新以进行提醒的一系列时间,但是我希望它不仅按时间排序,而且按 AM/PM 值排序。 这样数组看起来像这样:

["01:00 AM", "01:01 AM", "02:00 AM", "03:00 AM", "01:00 PM","01:01 PM"]

我怎样才能做到这一点? 在数组上使用.sort()不起作用,因为它只会按时间排序,但我特别希望 AM 字符串在 PM 字符串之前。 我将数组作为字符串,因为我认为它会更容易,但我看到这可能不是最好的方法。

按 12 & AM 过滤,然后排序。 按 12 和 PM 过滤,然后排序。 然后加入2个arrays。

let array = ["12:00 AM", "12:02 PM", "02:00 AM", "01:00 AM", "01:00 PM", "01:01 AM", "01:01 PM", "03:00 AM"]

我们需要考虑 #12 会影响排序。 所以需要用 12 过滤掉所有的时间,排序,放在前面。

let amc = array.filter { $0.hasPrefix("12") }.filter { $0.hasSuffix("AM") }.sorted(by: <) + array.filter { !$0.hasPrefix("12") }.filter { $0.hasSuffix("AM") }.sorted(by: <)
let pmc = array.filter { $0.hasPrefix("12") }.filter { $0.hasSuffix("PM") }.sorted(by: <) + array.filter { !$0.hasPrefix("12") }.filter { $0.hasSuffix("PM") }.sorted(by: <)
let comb = amc + pmc
print(comb) // prints ["12:00 AM", "01:00 AM", "01:01 AM", "02:00 AM", "03:00 AM", "12:02 PM", "01:00 PM", "01:01 PM"]

通过这个练习,很明显使用Date是最好的方法。

基于@nighttalker 的答案,您可以使用sorted(by: <)在一行中得到它。

那么代码将是:

let array = ["02:00 AM", "01:00 AM", "01:00 PM", "01:01 AM", "01:01 PM", "03:00 AM"]
let sortedArray = array.filter { $0.contains("AM") }.sorted(by: <) + array.filter { $0.contains("PM") }.sorted(by: <)

但正如 Arkku 所说,您可能应该使用 Date 类型并使其符合 Comparable。

(我还不能评论,所以必须这样提交)

let morningTimes = arrayOfTimes.filter{$0.contains("AM") && !$0.contains("12:")}.sorted()
let dayTimes = arrayOfTimes.filter{$0.contains("12:") && $0.contains("AM")}.sorted() + morningTimes
let nightTimes = arrayOfTimes.filter{$0.contains("PM") && !$0.contains("12:")}.sorted()
let allTimes = dayTimes + arrayOfTimes.filter{$0.contains("12:") && $0.contains("PM")}.sorted() + nightTimes

您可以传递sort块并在那里实现比较逻辑,例如:

var array = ["02:00 AM", "01:12 AM", "01:00 PM", "01:01 AM", "01:01 PM", "03:00 AM", "12:15 AM", "12:30 AM", "12:01 PM", "12:30 PM" ]
array.sort { s1, s2 in
    let isAM1 = s1.contains("AM")
    let isAM2 = s2.contains("AM")
    return isAM1 && !isAM2 || ((isAM1 == isAM2) && s1 < s2)
}

当且仅当第一个参数要排在第二个之前,比较块才应该返回true 这是在这里实现的,第一个是 AM,第二个是 PM,或者两者都是相同的 AM/PM,而第一个具有更早的时间。

PS您可能首先考虑使用Date对象而不是字符串(您始终可以根据需要将它们格式化回字符串)。

编辑:如果您的字符串使用“12:00 PM”为中午且“12:00 AM”为午夜的约定,则上述时间将错误地排序。 您可以通过测试s1.hasPrefix("12:")并反转“is AM”状态来解决这个问题:

if s1.hasPrefix("12:") {
    isAM1 = !isAM1
}
if s2.hasPrefix("12:") {
    isAM2 = !isAM2
}

即使这种方法最后排序是在上午12:59 AM ,而不是在01:00 AM之前进行排序——如果这是一个问题,您可以微调比较。 但是,我认为仅凭这种复杂性就足以有理由使用Date对象(或您自己的Comparable时间持有者)而不是字符串。 假设您不愿意切换到 24 小时制。 =)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM