オブジェクトの配列をSwiftのセットに削減しようとしていますが、これが私のコードです。
objects.reduce(Set<String>()) { $0.insert($1.URL) }
ただし、エラーが発生します。
Type of expression is ambiguous without more context.
URLのタイプは間違いなくStringであるため、問題が何であるかはわかりません。何か案は?
配列をセットに入れるために配列を減らす必要はありません。配列let objectSet = Set(objects.map { $0.URL })
を使用してセットを作成するだけです。
Swift 5.1では、問題を解決するために次の3つの例のいずれかを使用できます。
Array
の- map(_:)
メソッドとSet
の- init(_:)
初期化子の使用最も単純なケースでは、初期配列をurl
s(String
)の配列にマッピングし、その配列からセットを作成できます。以下のコードのプレイグラウンドは、その方法を示しています。
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
メソッドを作成できます。コードの下のプレイグラウンドは、その使用方法を示しています。
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()
メソッドは、戻り値結合値であるクロージャーを期待しますが、Set
値のinsert()
メソッドは何も返さず、代わりに既存の要素に新しい要素を挿入しますセットする。
機能させるには、次のようなことをする必要があります。
objects.reduce(Set<String>()) {
$0.union(CollectionOfOne($1.URL))
}
しかし、上記は少し不必要な複雑さです。大きな配列がある場合、Swiftがobjects
のすべての要素を処理している間に、非常に多くのセットが作成されることになります。 @NRitHのアドバイスに従い、map()
を使用すると、結果セットが一度に作成されます。
オブジェクトのURL
が厳密に型指定されたString
である場合、新しいSet<String>
オブジェクトを作成し、マップされた配列を持つセットでunionInPlace
を使用できます。
var mySet = Set<String>()
mySet.unionInPlace(objects.map { $0.URL as String })