Swift Set() 的 map(_:) 扩展?
Swift map(_:) extension for Set() ?
let numberSet = Set(1...11)
let divideSet = numberSet.map({ [=11=] / 10 })
//Error: Set does not have a member named map :(
Swift 1.2 支持 Set()
用于无序集合,但 map(_:)
似乎不适用于集合,所以我决定在我的操场上变聪明并尝试:
let stringSet = Set(map(numberSet, { String([=12=])}))
println(stringSet)
stringSet = ["2", "11", "1", "8", "6", "4", "3", "9", "7", "10", "5]
这似乎有效。
所以我尝试扩展 Set:
extension Set {
func map<U>(transform: (T) -> U) -> Set<U> {
return Set(Swift.map(self, transform)) }
}
Error: "couldn't find initialiser for Set(T) that accepts argument of type U"
而且我认为它不起作用是有充分理由的,就像这里的这个例子:
let smarDividSet = Set(map(numberSet, {[=14=] / 2}))
println(smarDividSet)
smartDividSet = "[5, 0, 2, 4, 1, 3]”
//Somehow elements is the Set are going missing.
关于如何扩展 Set 以可靠地使用 map(_:) 有什么想法吗?。
谢谢大家。
更新: Swift 2 和 3 发生了很多变化。通用的
Set
的占位符现在是 Element
而不是 T
,所有
集合有一个 map()
方法,其中 returns 一个 数组。
关于 Set -> Set
映射的问题(例如不同的元素映射到相同的结果)也给出了很好的论据。
另一方面,这种映射可能有一个用例,
所以这是 Swift 3 的更新(现在使用不同的名称)。
extension Set {
func setmap<U>(transform: (Element) -> U) -> Set<U> {
return Set<U>(self.lazy.map(transform))
}
}
示例:
let numberSet = Set(1...11)
let divideSet = numberSet.setmap { [=11=] / 2 }
print(divideSet) // [5, 0, 2, 4, 1, 3]
(旧答案:)你快到了。出于某种原因,
必须明确指定返回的集合:
extension Set {
func map<U>(transform: (T) -> U) -> Set<U> {
return Set<U>(Swift.map(self, transform))
}
}
示例:
let numberSet = Set(1...11)
let divideSet = numberSet.map { [=13=] / 2 }
println(divideSet) // [5, 0, 2, 4, 1, 3]
结果集的元素较少,因为整数除法
[=21=] / 2
截断 商,例如4/2 和 5/2 都映射到
相同的元素 2。浮点除法不会发生这种情况:
let floatdivideSet = numberSet.map { Double([=14=]) / 2.0 }
println(floatdivideSet) // [4.0, 5.0, 4.5, 5.5, 2.0, 3.0, 3.5, 2.5, 1.5, 1.0, 0.5]
另一个可能的实现是
extension Set {
func map<U>(transform: (T) -> U) -> Set<U> {
return Set<U>(lazy(self).map(transform))
}
}
这里 lazy(self)
returns 一个 LazyForwardCollection
其中有
map()
方法和 returns 又是 LazyForwardCollection
。
优点可能是没有创建中间数组。
Set.map(_:)
的问题与 Dictionary.map(_:)
相同,他们没有在 Swift
模块(标准库)中实现它,因为实际上 没有正确的方法 来实现它。原因是:map
ping 不仅仅是枚举(您可以对 for-in
中的任何 SequenceType
进行枚举),而是将每个值转换(使用参数闭包)到另一个值。所以你会期望结果中包含所有 transform(element)
,但是你猜怎么着,如果值相同,它们就会崩溃(对于 Dictionary
,只有键以这种方式表现)。
例如(与建议的实施)
Set([1, 2, 3, 4, 5]).map { 1 }.count == 1
这也是为什么 Swift.map
returns 一个 Array
而不是相同类型的 SequenceType
/CollectionType
作为 source
参数传递的原因.
稍稍题外话,Dictionary
(如前所述)在键值(基本上是 Set
)上有同样的问题,所以任何 map
Set<K>
或 Set<(K, V)>
不能确保一致的映射,但仅更改值就可以了。它不会是真正的 map
,因为 Dictionary
s 是元组的集合,而不仅仅是值。所以可能有类似于 mapValues
的东西是正确的,但在集合中仍然不是真正的 map
。
TL;DR
map
确实很有用,但要小心你实际在做什么,因为你不能 真的 做一个 map
从 Set
到 Set
.
从 Swift 2.0 开始,CollectionType
协议(由 Set
实现)有一个 map
方法。
我为 Set
做了扩展:
extension Set {
/// Map, but for a `Set`.
/// - Parameter transform: The transform to apply to each element.
func map<T>(_ transform: (Element) throws -> T) rethrows -> Set<T> {
var tempSet = Set<T>()
try forEach {
tempSet.insert(try transform([=10=]))
}
return tempSet
}
}
例如:
let someSet: Set<Int> = [1, 3, 5, 7]
print(someSet.map { [=11=] + 1 })
// Prints: [2, 6, 8, 4]
let numberSet = Set(1...11)
let divideSet = numberSet.map({ [=11=] / 10 })
//Error: Set does not have a member named map :(
Swift 1.2 支持 Set()
用于无序集合,但 map(_:)
似乎不适用于集合,所以我决定在我的操场上变聪明并尝试:
let stringSet = Set(map(numberSet, { String([=12=])}))
println(stringSet)
stringSet = ["2", "11", "1", "8", "6", "4", "3", "9", "7", "10", "5]
这似乎有效。 所以我尝试扩展 Set:
extension Set {
func map<U>(transform: (T) -> U) -> Set<U> {
return Set(Swift.map(self, transform)) }
}
Error: "couldn't find initialiser for Set(T) that accepts argument of type U"
而且我认为它不起作用是有充分理由的,就像这里的这个例子:
let smarDividSet = Set(map(numberSet, {[=14=] / 2}))
println(smarDividSet)
smartDividSet = "[5, 0, 2, 4, 1, 3]”
//Somehow elements is the Set are going missing.
关于如何扩展 Set 以可靠地使用 map(_:) 有什么想法吗?。 谢谢大家。
更新: Swift 2 和 3 发生了很多变化。通用的
Set
的占位符现在是 Element
而不是 T
,所有
集合有一个 map()
方法,其中 returns 一个 数组。
关于 Set -> Set
映射的问题(例如不同的元素映射到相同的结果)也给出了很好的论据。
另一方面,这种映射可能有一个用例,
所以这是 Swift 3 的更新(现在使用不同的名称)。
extension Set {
func setmap<U>(transform: (Element) -> U) -> Set<U> {
return Set<U>(self.lazy.map(transform))
}
}
示例:
let numberSet = Set(1...11)
let divideSet = numberSet.setmap { [=11=] / 2 }
print(divideSet) // [5, 0, 2, 4, 1, 3]
(旧答案:)你快到了。出于某种原因, 必须明确指定返回的集合:
extension Set {
func map<U>(transform: (T) -> U) -> Set<U> {
return Set<U>(Swift.map(self, transform))
}
}
示例:
let numberSet = Set(1...11)
let divideSet = numberSet.map { [=13=] / 2 }
println(divideSet) // [5, 0, 2, 4, 1, 3]
结果集的元素较少,因为整数除法
[=21=] / 2
截断 商,例如4/2 和 5/2 都映射到
相同的元素 2。浮点除法不会发生这种情况:
let floatdivideSet = numberSet.map { Double([=14=]) / 2.0 }
println(floatdivideSet) // [4.0, 5.0, 4.5, 5.5, 2.0, 3.0, 3.5, 2.5, 1.5, 1.0, 0.5]
另一个可能的实现是
extension Set {
func map<U>(transform: (T) -> U) -> Set<U> {
return Set<U>(lazy(self).map(transform))
}
}
这里 lazy(self)
returns 一个 LazyForwardCollection
其中有
map()
方法和 returns 又是 LazyForwardCollection
。
优点可能是没有创建中间数组。
Set.map(_:)
的问题与 Dictionary.map(_:)
相同,他们没有在 Swift
模块(标准库)中实现它,因为实际上 没有正确的方法 来实现它。原因是:map
ping 不仅仅是枚举(您可以对 for-in
中的任何 SequenceType
进行枚举),而是将每个值转换(使用参数闭包)到另一个值。所以你会期望结果中包含所有 transform(element)
,但是你猜怎么着,如果值相同,它们就会崩溃(对于 Dictionary
,只有键以这种方式表现)。
例如(与建议的实施)
Set([1, 2, 3, 4, 5]).map { 1 }.count == 1
这也是为什么 Swift.map
returns 一个 Array
而不是相同类型的 SequenceType
/CollectionType
作为 source
参数传递的原因.
稍稍题外话,Dictionary
(如前所述)在键值(基本上是 Set
)上有同样的问题,所以任何 map
Set<K>
或 Set<(K, V)>
不能确保一致的映射,但仅更改值就可以了。它不会是真正的 map
,因为 Dictionary
s 是元组的集合,而不仅仅是值。所以可能有类似于 mapValues
的东西是正确的,但在集合中仍然不是真正的 map
。
TL;DR
map
确实很有用,但要小心你实际在做什么,因为你不能 真的 做一个 map
从 Set
到 Set
.
从 Swift 2.0 开始,CollectionType
协议(由 Set
实现)有一个 map
方法。
我为 Set
做了扩展:
extension Set {
/// Map, but for a `Set`.
/// - Parameter transform: The transform to apply to each element.
func map<T>(_ transform: (Element) throws -> T) rethrows -> Set<T> {
var tempSet = Set<T>()
try forEach {
tempSet.insert(try transform([=10=]))
}
return tempSet
}
}
例如:
let someSet: Set<Int> = [1, 3, 5, 7]
print(someSet.map { [=11=] + 1 })
// Prints: [2, 6, 8, 4]