J'essaie de réduire un tableau d'objets à un ensemble dans Swift et voici mon code:
objects.reduce(Set<String>()) { $0.insert($1.URL) }
Cependant, j'obtiens une erreur:
Type of expression is ambiguous without more context.
Je ne comprends pas quel est le problème, car le type d'URL est certainement String. Des idées?
Il n'est pas nécessaire de réduire un tableau pour l'intégrer à un ensemble. il suffit de créer l'ensemble avec un tableau: let objectSet = Set(objects.map { $0.URL })
.
Avec Swift 5.1, vous pouvez utiliser l'un des trois exemples suivants pour résoudre votre problème.
Array
' map(_:)
méthode et Set
' init(_:)
initialiseurDans le cas le plus simple, vous pouvez mapper votre tableau initial sur un tableau de url
s (String
), puis créer un ensemble à partir de ce tableau. Le code de Playground ci-dessous montre comment procéder:
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"
reduce(into:_:)
de Array
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"
Alternativement, vous pouvez utiliser la méthode Array
de la méthode 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
Si nécessaire, vous pouvez créer une méthode mapToSet
pour Array
qui prend un paramètre de fermeture transform
et renvoie un Set
. Le code de Playground ci-dessous montre comment l'utiliser:
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"
La méthode reduce()
attend une fermeture qui retourne une valeur combinée, tandis que la méthode insert()
de Set
value ne renvoie rien, mais insère plutôt un nouvel élément dans l'ensemble existant.
Pour que cela fonctionne, vous devez faire quelque chose comme:
objects.reduce(Set<String>()) {
$0.union(CollectionOfOne($1.URL))
}
Mais ce qui précède est un peu une complication inutile. Si vous avez un grand tableau, cela signifierait un grand nombre d'ensembles en croissance constante tandis que Swift passe en revue tous les éléments de objects
. Suivez mieux les conseils de @NRitH et utilisez map()
comme cela produirait un ensemble résultant en une fois.
Si URL
sur votre objet est un String
fortement typé, vous pouvez créer un nouveau Set<String>
object et utilise unionInPlace
sur l’ensemble avec le tableau mappé:
var mySet = Set<String>()
mySet.unionInPlace(objects.map { $0.URL as String })