programing

Swift에서 설정할 배열 줄이기

nasanasas 2020. 11. 24. 08:03
반응형

Swift에서 설정할 배열 줄이기


객체 배열을 Swift에서 세트로 줄이려고하는데 이것이 내 코드입니다.

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

그러나 오류가 발생합니다.

Type of expression is ambiguous without more context.

URL 유형이 확실히 문자열이기 때문에 문제가 무엇인지 이해하지 못합니다. 어떤 아이디어?


집합으로 만들기 위해 배열을 줄일 필요가 없습니다. 배열로 세트를 만듭니다 let objectSet = Set(objects.map { $0.URL })..


Swift 5.1에서는 문제를 해결하기 위해 다음 세 가지 예제 중 하나를 사용할 수 있습니다.


#1. 사용 Arraymap(_:)방법 Setinit(_:)초기화를

가장 간단한 경우에는 초기 배열을 urls ( 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"

# 2. 사용 Arrayreduce(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"

대안으로 Arrayreduce(_:_:)방법을 사용할 수 있습니다 .

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()method는 결합 된 값 반환 하는 클로저를 기대 하지만 value의 insert()메서드는 Set아무것도 반환하지 않고 대신 기존 세트에 새 요소를 삽입합니다.

작동하게하려면 다음과 같은 작업을 수행해야합니다.

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

But the above is a bit of an unnecessary complication. If you have a big array, that would mean quite a number of ever-growing sets to be created while Swift goes over all the elements from objects. Better follow the advice from @NRitH and use map() as that would make a resulting set in one go.


If URL on your object is a strongly-typed String, you can create a new Set<String> object and use unionInPlace on the set with the mapped array:

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

참고URL : https://stackoverflow.com/questions/34161786/reduce-array-to-set-in-swift

반응형