如何在Swift中按数组元素分组
假设我有以下代码:
class Stat { var statEvents : [StatEvents] = []
}
struct StatEvents {
var name: String
var date: String
var hours: Int
}
var currentStat = Stat()
currentStat.statEvents = [
StatEvents(name: "lunch", date: "01-01-2015", hours: 1),
StatEvents(name: "dinner", date: "01-01-2015", hours: 1),
StatEvents(name: "dinner", date: "01-01-2015", hours: 1),
StatEvents(name: "lunch", date: "01-01-2015", hours: 1),
StatEvents(name: "dinner", date: "01-01-2015", hours: 1)
]
var filteredArray1 : [StatEvents] = []
var filteredArray2 : [StatEvents] = []
我可以手动调用下一个函数多次,以使2个数组按“相同名称”分组。
filteredArray1 = currentStat.statEvents.filter({$0.name == "dinner"})filteredArray2 = currentStat.statEvents.filter({$0.name == "lunch"})
问题是我不知道变量值,在这种情况下为“ dinner”和“
lunch”,因此我想按名称自动对这个statEvents数组进行分组,所以当名称不同时,我会得到尽可能多的数组。
我该怎么办?
回答:
斯威夫特4:
从Swift
4开始,此功能已添加到标准库中。您可以这样使用它:
Dictionary(grouping: statEvents, by: { $0.name })[
"dinner": [
StatEvents(name: "dinner", date: "01-01-2015", hours: 1),
StatEvents(name: "dinner", date: "01-01-2015", hours: 1),
StatEvents(name: "dinner", date: "01-01-2015", hours: 1)
],
"lunch": [
StatEvents(name: "lunch", date: "01-01-2015", hours: 1),
StatEvents(name: "lunch", date: "01-01-2015", hours: 1)
]
斯威夫特3:
public extension Sequence { func group<U: Hashable>(by key: (Iterator.Element) -> U) -> [U:[Iterator.Element]] {
var categories: [U: [Iterator.Element]] = [:]
for element in self {
let key = key(element)
if case nil = categories[key]?.append(element) {
categories[key] = [element]
}
}
return categories
}
}
不幸的是,append
上面的函数复制了基础数组,而不是对其进行适当的突变,这是更好的选择。这会导致很大的减速。您可以通过使用引用类型包装器解决该问题:
class Box<A> { var value: A
init(_ val: A) {
self.value = val
}
}
public extension Sequence {
func group<U: Hashable>(by key: (Iterator.Element) -> U) -> [U:[Iterator.Element]] {
var categories: [U: Box<[Iterator.Element]>] = [:]
for element in self {
let key = key(element)
if case nil = categories[key]?.value.append(element) {
categories[key] = Box([element])
}
}
var result: [U: [Iterator.Element]] = Dictionary(minimumCapacity: categories.count)
for (key,val) in categories {
result[key] = val.value
}
return result
}
}
即使您两次遍历最终字典,此版本在大多数情况下仍比原始字典快。
斯威夫特2:
public extension SequenceType { /// Categorises elements of self into a dictionary, with the keys given by keyFunc
func categorise<U : Hashable>(@noescape keyFunc: Generator.Element -> U) -> [U:[Generator.Element]] {
var dict: [U:[Generator.Element]] = [:]
for el in self {
let key = keyFunc(el)
if case nil = dict[key]?.append(el) { dict[key] = [el] }
}
return dict
}
}
在您的情况下,您可以keyFunc
使用以下名称返回“ keys” :
currentStat.statEvents.categorise { $0.name }[
dinner: [
StatEvents(name: "dinner", date: "01-01-2015", hours: 1),
StatEvents(name: "dinner", date: "01-01-2015", hours: 1),
StatEvents(name: "dinner", date: "01-01-2015", hours: 1)
], lunch: [
StatEvents(name: "lunch", date: "01-01-2015", hours: 1),
StatEvents(name: "lunch", date: "01-01-2015", hours: 1)
]
]
因此,您将获得一个字典,其中每个键都是一个名称,每个值都是具有该名称的StatEvents的数组。
斯威夫特1
func categorise<S : SequenceType, U : Hashable>(seq: S, @noescape keyFunc: S.Generator.Element -> U) -> [U:[S.Generator.Element]] { var dict: [U:[S.Generator.Element]] = [:]
for el in seq {
let key = keyFunc(el)
dict[key] = (dict[key] ?? []) + [el]
}
return dict
}
categorise(currentStat.statEvents) { $0.name }
给出输出:
extension StatEvents : Printable { var description: String {
return "\(self.name): \(self.date)"
}
}
print(categorise(currentStat.statEvents) { $0.name })
[
dinner: [
dinner: 01-01-2015,
dinner: 01-01-2015,
dinner: 01-01-2015
], lunch: [
lunch: 01-01-2015,
lunch: 01-01-2015
]
]
(swiftstub在这里)
以上是 如何在Swift中按数组元素分组 的全部内容, 来源链接: utcz.com/qa/432440.html