如何在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

回到顶部