我正在尝试将对象数组简化为Swift中的集合,这是我的代码:
objects.reduce(Set<String>()) { $0.insert($1.URL) }
但是,我得到一个错误:
Type of expression is ambiguous without more context.
我不明白问题是什么,因为URL的类型肯定是String。有任何想法吗?
Answers:
您不必简化数组就可以将其放入集合中。只需使用数组创建集合:let objectSet = Set(objects.map { $0.URL })
。
let objectSet = Set(objects.map { $0.URL })
。
使用Swift 5.1,您可以使用以下三个示例之一来解决您的问题。
Array
的map(_:)
方法和Set
的init(_:)
初始值设定项在最简单的情况下,您可以将初始数组映射到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"
Array
的reduce(into:_:)
方法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
的reduce(_:_:)
方法:
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"
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"
reduce()
方法期望闭包返回一个组合值,而值insert()
方法Set
不返回任何值,而是将一个新元素插入到现有集中。
为了使其正常工作,您需要执行以下操作:
objects.reduce(Set<String>()) {
$0.union(CollectionOfOne($1.URL))
}
但是以上只是一些不必要的复杂性。如果数组很大,则意味着Swift将遍历from中的所有元素时,将创建大量不断增长的集合objects
。最好遵循@NRitH的建议,并使用map()
它,因为这样可以一次性完成结果集。
func reduce<T>(_ initial: T, @noescape combine combine: (T, Self.Generator.Element) throws -> T) rethrows -> T
不是您要传递的签名。