【问题标题】:Swift: sort array of [Any] by item typeSwift:按项目类型对[Any]数组进行排序
【发布时间】:2019-05-12 20:41:06
【问题描述】:

我有一个包含不同类型对象的数组。在我的实际代码中,这些是符合相同协议的自定义类型,但该原则也适用于以下代码:

let anyObjectArray: [Any] = [51, "g", "hello", 1, 30111]

var sortedArray: [Any] = []

for item in anyObjectArray where item is Int {
    sortedArray.append(item)
}
for item in anyObjectArray where item is String {
    sortedArray.append(item)
}
print(sortedArray)

// 51, 1, 30111, "g", "hello"

如您所见,我想按项目类型对数组进行排序。

我想知道对数组进行多次迭代是否是一种合适的方法。是否有可能使用 .map 按项目类型对数组进行排序,如果是这样,效率会更高吗?

我的实际代码中的数组最多包含 4-5 个元素,有时只有一个,另一方面,不同的类型会比两个更多,因此 for in 循环的数量会更高(可能 4 -5)

【问题讨论】:

  • 按类型排序的目的是什么?通过一种类型提取或循环是微不足道的,那么为什么要排序呢?排序如何让数组变得更好?
  • 更好的是,这个数组真的是个好东西吗?协议数组在 Swift 中并不是一个真正有用的类型。

标签: arrays swift sorting types


【解决方案1】:

这几乎可以肯定是一个可怕的想法,并且几乎可以肯定掩盖了一个主要的类型错误,但并不难实现。正如您所说,您将按类型排序。由于类型不能直接比较,因此您可以按名称排序。

anyObjectArray.sorted { "\(type(of: $0))" < "\(type(of: $1))" }

但这深深地感觉Array 是错误的类型。感觉就像你真的想要一本字典。

【讨论】:

  • 到底是什么可怕的想法 - 尝试对数组进行排序,或者让数组存储不同类型并首先按类型顺序访问它们的想法?对类型名进行字符串插值并按其排序似乎是不需要的附加演员表,并限制我按字母顺序进行。不过,我需要一个定制订单。好的,我认为迭代实际上是最简单的方法
  • 如果你关心底层类型,你的意思不是协议。你的意思是一个枚举(带有相关数据)。使用枚举,按您想要的任何顺序进行排序都非常简单。从根本上说,如果您发现自己“偷看”了您已键入擦除的内容的底层类型(通过协议或“Any”),您几乎总是擦除了您不想擦除的类型。 (这里有一些极端情况例外,例如 print 和在某些情况下 Codable,但它们非常罕见。)
【解决方案2】:

这不会对数组进行排序,而是按字典中的类型对元素进行分组

var map = [String: [Any]]()

anyObjectArray.forEach( {
    let key = "\([type(of: $0))"
    if map[key] == nil { map[key] = [] }
    map[key]?.append($0)
})

或者 Rob Napier 建议的 Swift 4.2(或更高版本)

let map = Dictionary(grouping: anyObjectArray, by: { "\(type(of: $0))" })

【讨论】:

  • Swift 4.2 大大简化了这种方法:let map = Dictionary(grouping: anyObjectArray, by: { "\(type(of: $0))" })
  • @RobNapier 谢谢,看来我跟不上 4.2 的速度
猜你喜欢
  • 1970-01-01
  • 2016-11-04
  • 2020-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-23
  • 2021-01-28
  • 1970-01-01
相关资源
最近更新 更多