【问题标题】:Sorting array containing range as strings in iOS在iOS中将包含范围的数组排序为字符串
【发布时间】:2018-10-04 07:22:20
【问题描述】:

我在 sqlite 数据库中有一行范围格式的数据,如下面的屏幕截图所示。

我已将所有这些值作为字符串存储在一个数组中。现在,我必须对数组中的对象进行排序,以便结果如下所示并在表格视图中显示。

90 - 130 厘米

240 - 300 厘米

400 - 600 厘米

'>700 厘米

我已经尝试了一些代码。

示例代码 1:

 var arr = ["240 - 300 cm", "400 - 600 cm ", "90 - 130 cm", "<10 cm", ">700 cm"]
 var arr1 = arr.sorted{$0 < $1}

但是,这种方法似乎适用于带有字母数字字符的字符串。所以,我尝试了另一种方法。

示例代码 2:

var arr1 = [NSValue.init(range: NSMakeRange(240, 300)), NSValue.init(range: NSMakeRange(400, 600)), NSValue.init(range: NSMakeRange(90, 130))]
var arr2 = arr1.sorted{$0.rangeValue.location < $1.rangeValue.location}

for range in arr2 {
    print("\(range.rangeValue.location) - \(range.rangeValue.length) cm")
}

但是,要使这种方法起作用,我必须执行以下操作:

  • 根据要求以格式(例如 90 - 130 厘米)处理数据,以便我可以将其混合以适应 NSRange。

  • 对于像 700 cm 这样的值,我必须单独处理。可能是,通过在数组排序后将这些值插入到第一个索引和最后一个索引中,尚未尝试。

  • 数组排序后,再次以我在上面示例代码中使用 for 循环完成的正确格式打印值。

这种方法似乎在权衡大量时间消耗和操作。我不知道如果有 100 行这样的数据,性能会如何。

我的问题是,有没有更好更简洁的方法来在 iOS 中对范围格式的数据进行排序?

非常感谢任何帮助。

【问题讨论】:

  • 问题:如果字符串以“总是的第一个元素? ">" 一样,是不是表示它应该是总是排序数组中的最后一个元素?
  • 是的@Ahmad F,我查看了更多此类范围数据的样本,我很确定在小于 () 运算符之后不会有任何数据.它们代表列表的最小和最大限制。

标签: arrays swift string sorting


【解决方案1】:

我认为如果你只有 100 个这样的条目,那么创建一个 slow 算法将非常困难。您几乎可以做任何您想做的事情,并且无法识别任何性能影响 - 至少不是毫秒级的。

如果您有非常多 量的数据,并且您经常排序(例如,排序的频率高于数据更改的频率),一种解决方案是非规范化您的数据库:

  • 创建一个单独的行normalizedLength 或其他东西
  • 解析所有数据,将“90 - 130 cm”之类的内容转换为整数值90 并将其存储到normalizedLength
  • Int.maxInt.min 用于那些“> ...”和“

这必须为您的所有数据执行一次。然后,您可以对其进行多次排序等。

【讨论】:

  • 你的意思是说创建单独的列normalizedLength,并存储ex的下限。 90在数据90-130旁边的列中,并根据normalizedLength排序。
  • 是的。由于范围不重叠(我猜),只有下限是相关的。
【解决方案2】:

虽然它可能不是最优雅的解决方案,但您可以通过检查每个字符串的第一个元素来实现它,从而实现所需的排序:

var arr = ["240 - 300 cm", "400 - 600 cm ", "90 - 130 cm", "<10 cm", ">700 cm"]

func sortMyArray(_ array: [String]) -> [String] {
    var lessThanElements = [String]()
    var defaultPatternElements = [String]()
    var greaterThanElements = [String]()

    for srting in array {
        switch srting.first! {
        case "<":
            lessThanElements.append(srting)
        case ">":
            greaterThanElements.append(srting)
        default:
            defaultPatternElements.append(srting)
        }
    }

    return lessThanElements.sorted() + defaultPatternElements.sorted() + greaterThanElements.sorted()
}

let sortedArray = sortMyArray(arr)
print(sortedArray) // ["<10 cm", "240 - 300 cm", "400 - 600 cm ", "90 - 130 cm", ">700 cm"]

请注意,如果字符串的第一个字符不是“”,则将其视为defaultPatternElements元素。

【讨论】:

  • 不错的尝试。谢谢。
【解决方案3】:

此解决方案检查字符串的第一个字符。如果它可以转换为Int,请使用整个字符串,如果不是,请删除第一个字符并使用它。然后使用选项numeric 执行常规compare 排序

let arr = ["240 - 300 cm", "400 - 600 cm ", "90 - 130 cm", "<10 cm", ">700 cm"]

let arr1 = arr.sorted { (str1, str2) -> Bool in
    let lhs = Int(str1.prefix(1)) == nil ? String(str1.dropFirst()) : str1
    let rhs = Int(str2.prefix(1)) == nil ? String(str2.dropFirst()) : str2
    return rhs.compare(lhs, options: .numeric) == .orderedDescending
}

print(arr1)

【讨论】:

    猜你喜欢
    • 2018-11-02
    • 2013-12-23
    • 1970-01-01
    • 2013-02-13
    • 2013-11-03
    • 1970-01-01
    • 1970-01-01
    • 2020-02-18
    相关资源
    最近更新 更多