[arrays] Swift의 배열에서 중복 요소 제거

요즘 Swift에서는 간단히 입력 Set( yourArray )하여 배열을 고유하게 만듭니다. (또는 필요한 경우 주문 세트.)

그 전에는 어떻게 되었습니까?


다음과 같은 배열이있을 수 있습니다.

[1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]

또는 실제로 같은 유형의 데이터 부분 시퀀스. 내가하고 싶은 것은 각각의 동일한 요소 중 하나만 있는지 확인하는 것입니다. 예를 들어 위의 배열은 다음과 같습니다.

[1, 4, 2, 6, 24, 15, 60]

2, 6 및 15의 복제본이 제거되어 동일한 각 요소 중 하나만 있음을 확인했습니다. Swift가이를 쉽게 수행 할 수있는 방법을 제공합니까, 아니면 직접해야합니까?



답변

예를 들어 다음과 같이 직접 롤백 할 수 있습니다 ( Swift 1.2에서 Set로 업데이트 )

func uniq<S : SequenceType, T : Hashable where S.Generator.Element == T>(source: S) -> [T] {
    var buffer = [T]()
    var added = Set<T>()
    for elem in source {
        if !added.contains(elem) {
            buffer.append(elem)
            added.insert(elem)
        }
    }
    return buffer
}

let vals = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
let uniqueVals = uniq(vals) // [1, 4, 2, 6, 24, 15, 60]

스위프트 3 버전 :

func uniq<S : Sequence, T : Hashable>(source: S) -> [T] where S.Iterator.Element == T {
    var buffer = [T]()
    var added = Set<T>()
    for elem in source {
        if !added.contains(elem) {
            buffer.append(elem)
            added.insert(elem)
        }
    }
    return buffer
}

그리고 다음의 확장으로 Array:

extension Array where Element: Hashable {
    var uniques: Array {
        var buffer = Array()
        var added = Set<Element>()
        for elem in self {
            if !added.contains(elem) {
                buffer.append(elem)
                added.insert(elem)
            }
        }
        return buffer
    }
}


답변

집합으로 변환하고 다시 배열로 쉽게 다시 변환 할 수 있습니다.

let unique = Array(Set(originals))

어레이의 원래 순서를 유지한다고 보장 할 수는 없습니다.


답변

여기에 많은 답변이 있지만 Swift 2 이상에 적합한이 간단한 확장을 놓쳤습니다.

extension Array where Element:Equatable {
    func removeDuplicates() -> [Element] {
        var result = [Element]()

        for value in self {
            if result.contains(value) == false {
                result.append(value)
            }
        }

        return result
    }
}

매우 간단합니다. 다음과 같이 호출 할 수 있습니다.

let arrayOfInts = [2, 2, 4, 4]
print(arrayOfInts.removeDuplicates()) // Prints: [2, 4]

속성을 기반으로 필터링

속성을 기준으로 배열을 필터링하려면이 방법을 사용할 수 있습니다.

extension Array {

    func filterDuplicates(@noescape includeElement: (lhs:Element, rhs:Element) -> Bool) -> [Element]{
        var results = [Element]()

        forEach { (element) in
            let existingElements = results.filter {
                return includeElement(lhs: element, rhs: $0)
            }
            if existingElements.count == 0 {
                results.append(element)
            }
        }

        return results
    }
}

다음과 같이 전화를 걸 수 있습니다.

let filteredElements = myElements.filterDuplicates { $0.PropertyOne == $1.PropertyOne && $0.PropertyTwo == $1.PropertyTwo }


답변

스위프트 3.0

let uniqueUnordered = Array(Set(array))
let uniqueOrdered = Array(NSOrderedSet(array: array))


답변

코드에 두 확장을 모두 넣으면 Hashable가능 하면 더 빠른 버전이 Equatable사용되며 대체 버전으로 사용됩니다.

public extension Sequence where Element: Hashable {
  var firstUniqueElements: [Element] {
    var set: Set<Element> = []
    return filter { set.insert($0).inserted }
  }
}

public extension Sequence where Element: Equatable {
  var firstUniqueElements: [Element] {
    reduce(into: []) { uniqueElements, element in
      if !uniqueElements.contains(element) {
        uniqueElements.append(element)
      }
    }
  }
}

순서가 중요하지 않은 경우 항상 이 Set initializer 만 사용할 수 있습니다 .


답변

Swift 4 이상 편집 / 업데이트

또한 RangeReplaceableCollection프로토콜을 확장 하여 StringProtocol유형 에도 사용할 수 있습니다.

extension RangeReplaceableCollection where Element: Hashable {
    var orderedSet: Self {
        var set = Set<Element>()
        return filter { set.insert($0).inserted }
    }
    mutating func removeDuplicates() {
        var set = Set<Element>()
        removeAll { !set.insert($0).inserted }
    }
}

let integers = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
let integersOrderedSet = integers.orderedSet // [1, 4, 2, 6, 24, 15, 60]

"abcdefabcghi".orderedSet  // "abcdefghi"
"abcdefabcghi".dropFirst(3).orderedSet // "defabcghi"

돌연변이 방법 :

var string = "abcdefabcghi"
string.removeDuplicates()
string  //  "abcdefghi"

var substring = "abcdefabcdefghi".dropFirst(3)  // "defabcdefghi"
substring.removeDuplicates()
substring   // "defabcghi"

들어 스위프트 3 클릭 여기


답변

스위프트 4

public extension Array where Element: Hashable {
    func uniqued() -> [Element] {
        var seen = Set<Element>()
        return filter{ seen.insert($0).inserted }
    }
}

모든 시도 insert는 또한 튜플을 반환합니다 : (inserted: Bool, memberAfterInsert: Set.Element). 설명서를 참조하십시오 .

반환 된 값을 사용하면 루핑이나 다른 작업을 피할 수 있습니다.