你需要修改
groupBy
扩展,将其分组为一个2元组的数组而不是一个字典,其中第一个元组元素对应于非唯一“键”,第二个元组元素是
self
数组中可以归类到给定键的后续元素的数组。
修改后的SequenceType
扩展
extension SequenceType {
func groupBy<U : Comparable>(@noescape keyFunc: Generator.Element -> U) -> [(U,[Generator.Element])] {
var tupArr: [(U,[Generator.Element])] = []
for el in self {
let key = keyFunc(el)
if tupArr.last?.0 == key {
tupArr[tupArr.endIndex-1].1.append(el)
}
else {
tupArr.append((key,[el]))
}
}
return tupArr
}
}
请注意,现在扩展中的通用
U
只需要符合
Comparable
即可,因为我们只将
U
元素用作元组中的“虚拟”键。
调用扩展
通过这种修改,我们可以这样调用 groupBy(..)
方法:
let array = ["23.88", "24", "30", "24.16#C", "25#C", "12", "24.44", "50" , "31#O", "40#O" , "44#C", "55#C"]
/* assuming we know the last character always describe the mode,
given one is included (#) */
let groupedArray: [(String,[String])] = array.groupBy {
guard $0.characters.contains("#") else { return "No mode" }
return "mode = " + String($0.characters.last!)
}
print(groupedArray)
/* [("No mode", ["23.88", "24", "30"]),
("mode = C", ["24.16#C", "25#C"]),
("No mode", ["12", "24.44", "50"]),
("mode = O", ["31#O", "40#O"]),
("mode = C", ["44#C", "55#C"])] */
从分组的数组中删除原始模式标记(#X
)
如果您想要在结果数组中删除原始模式标记(#X
),可以在调用 groupBy
后应用额外的 map
操作。
将具有字符串值的标记移除:
let groupedArrayClean = groupedArray.map { ($0.0, $0.1.map {
String($0.characters.prefixUpTo($0.characters.indexOf("#") ?? $0.characters.endIndex))
})
}
print(groupedArrayClean)
或者,使用结果值为
Double
:
let groupedArrayClean = groupedArray.map { ($0.0, $0.1.flatMap {
Double(
String(($0.characters.prefixUpTo($0.characters.indexOf("#") ?? $0.characters.endIndex))))
})
}
print(groupedArrayClean)
或者:在单个链接调用中对模式标记进行分组和清理
或者,一次性使用groupBy
和map
,不需要中间赋值:
let groupedArrayClean: [(String,[String])] = array.groupBy {
guard $0.characters.contains("#") else { return "No mode" }
return "mode = " + String($0.characters.last!)
}
.map { ($0.0, $0.1.map {
String($0.characters
.prefixUpTo($0.characters.indexOf("#") ?? $0.characters.endIndex))
})
}
(类似地,对于生成的
Double
值情况也是如此。)
keyFunc
代码和扩展方法的实际调用。 - BaseZen