减少要在Swift中设置的数组

时间:2015-12-08 17:04:11

标签: arrays swift set reduce

我正在尝试将一个对象数组减少到Swift中的一个集合,这是我的代码:

objects.reduce(Set<String>()) { $0.insert($1.URL) }

然而,我收到错误:

Type of expression is ambiguous without more context.

我不明白问题是什么,因为URL的类型肯定是String。有什么想法吗?

4 个答案:

答案 0 :(得分:90)

您不必减少数组以将其放入集合中;只需使用数组创建集合:let objectSet = Set(objects.map { $0.URL })

答案 1 :(得分:5)

reduce()方法需要一个返回组合值的闭包,而insert()值的Set方法不返回任何内容,而是插入一个新元素进入现有的集合。

为了使其有效,您需要执行以下操作:

objects.reduce(Set<String>()) {
    $0.union(CollectionOfOne($1.URL))
}

但上述情况有点不必要。如果你有一个大数组,这意味着要创建相当多的不断增长的集合,而Swift会覆盖objects的所有元素。更好地遵循@NRitH的建议并使用map(),因为这样可以一次性生成结果集。

答案 2 :(得分:3)

使用Swift 4.2,您可以使用以下三个示例之一来解决您的问题。


#1。使用Array的{​​{3}}方法和Set的{​​{3}}初始化程序

在最简单的情况下,您可以将初始数组映射到url s(String)的数组,然后从该数组创建一个集合。下面的Playground代码显示了操作方法:

struct MyObject {
    let url: String
}

let objectArray = [
    MyObject(url: "mozilla.org"),
    MyObject(url: "gnu.org"),
    MyObject(url: "git-scm.com")
]

let urlArray = objectArray.map({ $0.url })
let urlSet = Set(urlArray)
dump(urlSet)
// ▿ 3 members
//   - "git-scm.com"
//   - "mozilla.org"
//   - "gnu.org"

#2。使用Array的{​​{3}}方法

struct MyObject {
    let url: String
}

let objectArray = [
    MyObject(url: "mozilla.org"),
    MyObject(url: "gnu.org"),
    MyObject(url: "git-scm.com")
]

let urlSet = objectArray.reduce(into: Set<String>(), { (urls, object) in
    urls.insert(object.url)
})
dump(urlSet)
// ▿ 3 members
//   - "git-scm.com"
//   - "mozilla.org"
//   - "gnu.org"

或者,您可以使用Array的{​​{3}}方法:

struct MyObject {
    let url: String
}

let objectArray = [
    MyObject(url: "mozilla.org"),
    MyObject(url: "gnu.org"),
    MyObject(url: "git-scm.com")
]

let urlSet = objectArray.reduce(Set<String>(), { (partialSet, object) in
    var urls = partialSet
    urls.insert(object.url)
    return urls
})
dump(urlSet)
// ▿ 3 members
//   - "git-scm.com"
//   - "mozilla.org"
//   - "gnu.org"

#3。使用Array扩展名

如有必要,您可以为mapToSet创建一个Array方法,该方法采用一个transform闭包参数并返回一个Set。下面的Playground代码显示了如何使用它:

extension Array {

    func mapToSet<T: Hashable>(_ transform: (Element) -> T) -> Set<T> {
        var result = Set<T>()
        for item in self {
            result.insert(transform(item))
        }
        return result
    }

}

struct MyObject {
    let url: String
}

let objectArray = [
    MyObject(url: "mozilla.org"),
    MyObject(url: "gnu.org"),
    MyObject(url: "git-scm.com")
]

let urlSet = objectArray.mapToSet({ $0.url })
dump(urlSet)
// ▿ 3 members
//   - "git-scm.com"
//   - "mozilla.org"
//   - "gnu.org"

答案 3 :(得分:0)

如果您的对象上的URL是强类型String,您可以创建一个新的Set<String>对象,并在映射数组的集合上使用unionInPlace: / p>

var mySet = Set<String>()
mySet.unionInPlace(objects.map { $0.URL as String })