Rub*_*ben 72 arrays nsarray ios 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] = []
Run Code Online (Sandbox Code Playgroud)
我可以手动调用下一个函数,以便有两个按"同名"分组的数组.
filteredArray1 = currentStat.statEvents.filter({$0.name == "dinner"})
filteredArray2 = currentStat.statEvents.filter({$0.name == "lunch"})
Run Code Online (Sandbox Code Playgroud)
问题是我不知道变量值,在这种情况下是"晚餐"和"午餐",所以我想按名称自动对这个statEvents数组进行分组,所以我得到的数量与名称不同的数组一样多.
我怎么能这样做?
ois*_*sdk 150
自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)
]
Run Code Online (Sandbox Code Playgroud)
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
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,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
}
}
Run Code Online (Sandbox Code Playgroud)
即使您遍历最终字典两次,在大多数情况下,此版本仍然比原始字典更快.
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
}
}
Run Code Online (Sandbox Code Playgroud)
在您的情况下,您可以将返回的"键" keyFunc作为名称:
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)
]
]
Run Code Online (Sandbox Code Playgroud)
因此,您将获得一个字典,其中每个键都是一个名称,每个值都是具有该名称的StatEvents数组.
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 }
Run Code Online (Sandbox Code Playgroud)
这给出了输出:
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
]
]
Run Code Online (Sandbox Code Playgroud)
(swiftstub在这里)
Ima*_*tit 51
使用Swift 4,Dictionary有一个名为的初始化方法init(grouping:by:).init(grouping:by:)有以下声明:
init<S>(grouping values: S, by keyForValue: (S.Element) throws -> Key) rethrows where Value == [S.Element], S : Sequence
Run Code Online (Sandbox Code Playgroud)
创建一个新的字典,其中键是给定闭包返回的分组,值是返回每个特定键的元素的数组.
以下Playground代码显示了如何使用init(grouping:by:)以解决您的问题:
struct StatEvents: CustomStringConvertible {
let name: String
let date: String
let hours: Int
var description: String {
return "Event: \(name) - \(date) - \(hours)"
}
}
let statEvents = [
StatEvents(name: "lunch", 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)
]
let dictionary = Dictionary(grouping: statEvents, by: { (element: StatEvents) in
return element.name
})
//let dictionary = Dictionary(grouping: statEvents) { $0.name } // also works
print(dictionary)
/*
prints:
[
"dinner": [Event: dinner - 01-01-2015 - 1, Event: dinner - 01-01-2015 - 1],
"lunch": [Event: lunch - 01-01-2015 - 1, Event: lunch - 01-01-2015 - 1]
]
*/
Run Code Online (Sandbox Code Playgroud)
小智 30
Swift 4:你可以使用来自 apple开发者网站的init(分组:by :)
示例:
let students = ["Kofi", "Abena", "Efua", "Kweku", "Akosua"]
let studentsByLetter = Dictionary(grouping: students, by: { $0.first! })
// ["E": ["Efua"], "K": ["Kofi", "Kweku"], "A": ["Abena", "Akosua"]]
Run Code Online (Sandbox Code Playgroud)
所以在你的情况下
let dictionary = Dictionary(grouping: currentStat.statEvents, by: { $0.name! })
Run Code Online (Sandbox Code Playgroud)
mie*_*tus 26
对于Swift 3:
public extension Sequence {
func categorise<U : Hashable>(_ key: (Iterator.Element) -> U) -> [U:[Iterator.Element]] {
var dict: [U:[Iterator.Element]] = [:]
for el in self {
let key = key(el)
if case nil = dict[key]?.append(el) { dict[key] = [el] }
}
return dict
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
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)
]
]
Run Code Online (Sandbox Code Playgroud)
在Swift 4中,此扩展程序具有最佳性能,可帮助您的运营商实现链接
extension Sequence {
func group<U: Hashable>(by key: (Iterator.Element) -> U) -> [U:[Iterator.Element]] {
return Dictionary.init(grouping: self, by: key)
}
}
Run Code Online (Sandbox Code Playgroud)
例:
struct Asset {
let coin: String
let amount: Int
}
let assets = [
Asset(coin: "BTC", amount: 12),
Asset(coin: "ETH", amount: 15),
Asset(coin: "BTC", amount: 30),
]
let grouped = assets.group(by: { $0.coin })
Run Code Online (Sandbox Code Playgroud)
创建:
[
"ETH": [
Asset(coin: "ETH", amount: 15)
],
"BTC": [
Asset(coin: "BTC", amount: 12),
Asset(coin: "BTC", amount: 30)
]
]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
47482 次 |
| 最近记录: |