开发者社区> 问答> 正文

如何在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数组分组,所以我会得到与名称不同时一样多的数组。

我该怎么办? 问题来源于stack overflow

展开
收起
保持可爱mmm 2020-02-08 19:43:34 1115 0
1 条回答
写回答
取消 提交回答
  • 斯威夫特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 { 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(@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 ] ]

    2020-02-08 19:43:49
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
OpenStack Swift 海量小文件优化之路 立即下载
From Java/Android to Swift iOS 立即下载
Swift在Airbnb的应用实践 立即下载