14
  let numberSet = Set(1...11)
  let divideSet = numberSet.map({  $0 / 10 }) 
  //Error: Set does not have a member named map   :(

Swift 1.2 支持Set()无序集合,但map(_:)似乎不适用于 Sets,所以我决定在我的操场上变得聪明并尝试:

 let stringSet = Set(map(numberSet, { String($0)}))
 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, {$0 / 2})) 
   println(smarDividSet)
   smartDividSet = "[5, 0, 2, 4, 1, 3]” 
  //Somehow elements is the Set are going missing.

关于如何扩展 Set 以可靠地使用 map(_:) 的任何想法?谢谢大家。

4

4 回答 4

14

更新: Swift 2 和 3 发生了很大的变化。通用占位符Set现在是Element而不是T,并且所有集合都有一个map()返回数组的方法。

关于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 { $0 / 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 { $0 / 2 }
println(divideSet) // [5, 0, 2, 4, 1, 3]

结果集的元素较少,因为整数除法 会$0 / 2 截断商,例如 4/2 和 5/2 都映射到同一个元素 2。浮点除法不会发生这种情况:

let floatdivideSet = numberSet.map { Double($0) / 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)返回一个LazyForwardCollection有一个map()方法的,然后LazyForwardCollection又返回一个。优点可能是没有创建中间数组。

于 2015-03-17T20:35:37.177 回答
9

的问题与Set.map(_:)相同Dictionary.map(_:),他们没有在Swift模块(标准库)中实现它,因为实际上没有正确的方法来实现它。原因是:mapping 不仅仅是枚举(您可以使用SequenceTypea 中的任何一个for-in),而是将每个值(使用参数闭包)转换为另一个值。所以你会期望结果会包含所有的transform(element),但是猜猜看,如果值相同,它们会崩溃(对于Dictionarys 只有键以这种方式运行)。

例如(与建议的实施) Set([1, 2, 3, 4, 5]).map { 1 }.count == 1

这也是为什么Swift.map返回与参数传递的/Array类型不同的原因。SequenceTypeCollectionTypesource

稍微离题一点,Dictionary(如前所述)在键值(基本上是 a Set)上存在相同的问题,因此任何map在 theSet<K>或 the上工作的Set<(K, V)>都不能确保一致的映射,但仅更改值的将是好的。这不是真的map,因为Dictionarys 是元组的集合,而不仅仅是值。所以可能有一些类似的东西是正确的,但在收藏中mapValues仍然不是真的。map

TL;博士

map真的很有用,但要小心你实际在做什么,因为你不能真正做 a mapfrom Setto Set

于 2015-04-20T11:37:55.400 回答
1

从 Swift 2.0 开始,CollectionType协议(由 实现Set)有一个map方法。

于 2015-11-04T09:19:24.887 回答
0

我做了一个扩展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($0))
        }

        return tempSet
    }
}

例如:

let someSet: Set<Int> = [1, 3, 5, 7]
print(someSet.map { $0 + 1 })

// Prints:  [2, 6, 8, 4]
于 2019-12-16T12:08:57.993 回答