programing

Swift에서 어레이에서 중복 요소 제거

css3 2023. 4. 10. 22:05

Swift에서 어레이에서 중복 요소 제거

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

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

또는 실제로 데이터의 유사한 유형의 모든 부분 시퀀스를 사용할 수 있습니다.각 요소가 동일한지 확인합니다.예를 들어 위의 어레이는 다음과 같습니다.

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

2, 6, 및 15 의 중복은 각 동일한 요소가1개만 존재하는지 확인하기 위해 삭제되었습니다.Swift는 이 작업을 쉽게 수행할 수 있는 방법을 제공합니까? 아니면 제가 직접 수행해야 합니까?

은 할 수 .Set 로로 an an an로 Array시시시시시시:

let unique = Array(Set(originals))

이렇게 하면 어레이의 원래 순서를 유지할 수 없습니다.

예를 들어 다음과 같이 직접 굴릴 수 있습니다.

func unique<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
}

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

리리 for for for for의 Array:

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

또는 보다 우아하게 (Swift 4/5) :

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

어떤 것이 사용됩니까?

[1,2,4,2,1].uniqued()  // => [1,2,4]

스위프트 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)매뉴얼을 참조해 주세요.

반환된 값을 사용하는 것은 여러 루프를 회피할 수 있음을 의미하므로 이것이 O(n)입니다.

사용하다Set ★★★★★★★★★★★★★★★★★」NSOrderedSetArray:

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

여기에서는 많은 답변을 얻을 수 있지만, 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 }

를 입력하면, 「」의 .Hashable한 하고, 「버전」을 사용합니다.Equatable이치노

public extension Sequence where Element: Hashable {
  /// The elements of the sequence, with duplicates removed.
  /// - Note: Has equivalent elements to `Set(self)`.
  var firstUniqueElements: [Element] {
    let getSelf: (Element) -> Element = \.self
    return firstUniqueElements(getSelf)
  }
}

public extension Sequence where Element: Equatable {
  /// The elements of the sequence, with duplicates removed.
  /// - Note: Has equivalent elements to `Set(self)`.
  var firstUniqueElements: [Element] {
    let getSelf: (Element) -> Element = \.self
    return firstUniqueElements(getSelf)
  }
}

public extension Sequence {
  /// The elements of the sequences, with "duplicates" removed
  /// based on a closure.
  func firstUniqueElements<Hashable: Swift.Hashable>(
    _ getHashable: (Element) -> Hashable
  ) -> [Element] {
    var set: Set<Hashable> = []
    return filter { set.insert(getHashable($0)).inserted }
  }

  /// The elements of the sequence, with "duplicates" removed,
  /// based on a closure.
  func firstUniqueElements<Equatable: Swift.Equatable>(
    _ getEquatable: (Element) -> Equatable
  ) -> [Element] {
    reduce(into: []) { uniqueElements, element in
      if zip(
        uniqueElements.lazy.map(getEquatable),
        AnyIterator { [equatable = getEquatable(element)] in equatable }
      ).allSatisfy(!=) {
        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"

Swift 3의 경우 여기를 클릭하십시오.

스위프트 4

계속 주문할 수 있습니다.

extension Array where Element: Equatable {
    func removingDuplicates() -> Array {
        return reduce(into: []) { result, element in
            if !result.contains(element) {
                result.append(element)
            }
        }
    }
}

https://www.swiftbysundell.com/posts/the-power-of-key-paths-in-swift,에서 영감을 받아 모든 keyPath에서 유니시티를 필터링할 수 있는 보다 강력한 툴을 선언할 수 있습니다.복잡성에 관한 다양한 답변에 대한 Alexander의 코멘트 덕분에 다음 솔루션은 거의 최적의 솔루션이 될 것입니다.

변이하지 않는 용액

모든 keyPath에서 유니시티를 필터링할 수 있는 기능을 사용하여 확장합니다.

extension RangeReplaceableCollection {
    /// Returns a collection containing, in order, the first instances of
    /// elements of the sequence that compare equally for the keyPath.
    func unique<T: Hashable>(for keyPath: KeyPath<Element, T>) -> Self {
        var unique = Set<T>()
        return filter { unique.insert($0[keyPath: keyPath]).inserted }
    }
}

주의: 객체가 RangeReplaceableCollection에 준거하지 않지만 Sequence에 준거한 경우에는 다음과 같은 확장자를 추가할 수 있지만 반환 유형은 항상 Array입니다.

extension Sequence {
    /// Returns an array containing, in order, the first instances of
    /// elements of the sequence that compare equally for the keyPath.
    func unique<T: Hashable>(for keyPath: KeyPath<Element, T>) -> [Element] {
        var unique = Set<T>()
        return filter { unique.insert($0[keyPath: keyPath]).inserted }
    }
}

사용.

요소을 원하는 keyPath를 합니다.\.self:

let a = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
let b = a.unique(for: \.self)
/* b is [1, 4, 2, 6, 24, 15, 60] */

다른 것에 대해 통일성을 원하는 경우(예:idkeyPath를합니다.

let a = [CGPoint(x: 1, y: 1), CGPoint(x: 2, y: 1), CGPoint(x: 1, y: 2)]
let b = a.unique(for: \.y)
/* b is [{x 1 y 1}, {x 1 y 2}] */

변이 솔루션

모든 keyPath에서 유니시티를 필터링할 수 있는 변환 함수를 사용하여 확장합니다.

extension RangeReplaceableCollection {
    /// Keeps only, in order, the first instances of
    /// elements of the collection that compare equally for the keyPath.
    mutating func uniqueInPlace<T: Hashable>(for keyPath: KeyPath<Element, T>) {
        var unique = Set<T>()
        removeAll { !unique.insert($0[keyPath: keyPath]).inserted }
    }
}

사용.

요소을 원하는 keyPath를 합니다.\.self:

var a = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
a.uniqueInPlace(for: \.self)
/* a is [1, 4, 2, 6, 24, 15, 60] */

다른 것에 대해 통일성을 원하는 경우(예:idkeyPath를합니다.

var a = [CGPoint(x: 1, y: 1), CGPoint(x: 2, y: 1), CGPoint(x: 1, y: 2)]
a.uniqueInPlace(for: \.y)
/* a is [{x 1 y 1}, {x 1 y 2}] */

여기 카테고리가 있습니다.SequenceType명령어는 하지만 """를 사용합니다.Set 하다contains하여 " "를 합니다.O(n)contains(_:)★★★★★★ 。

public extension Sequence where Element: Hashable {

    /// Return the sequence with all duplicates removed.
    ///
    /// i.e. `[ 1, 2, 3, 1, 2 ].uniqued() == [ 1, 2, 3 ]`
    ///
    /// - note: Taken from stackoverflow.com/a/46354989/3141234, as 
    ///         per @Alexander's comment.
    func uniqued() -> [Element] {
        var seen = Set<Element>()
        return self.filter { seen.insert($0).inserted }
    }
}

해시 또는 Equatable이 아닌 경우 술어를 전달하여 동등성 검사를 수행할 수 있습니다.

extension Sequence {

    /// Return the sequence with all duplicates removed.
    ///
    /// Duplicate, in this case, is defined as returning `true` from `comparator`.
    ///
    /// - note: Taken from stackoverflow.com/a/46354989/3141234
    func uniqued(comparator: @escaping (Element, Element) throws -> Bool) rethrows -> [Element] {
        var buffer: [Element] = []

        for element in self {
            // If element is already in buffer, skip to the next element
            if try buffer.contains(where: { try comparator(element, $0) }) {
                continue
            }

            buffer.append(element)
        }

        return buffer
    }
}

해시 가능은 없지만 Equatable인 경우 다음 방법을 사용할 수 있습니다.

extension Sequence where Element: Equatable {

    /// Return the sequence with all duplicates removed.
    ///
    /// i.e. `[ 1, 2, 3, 1, 2 ].uniqued() == [ 1, 2, 3 ]`
    ///
    /// - note: Taken from stackoverflow.com/a/46354989/3141234
    func uniqued() -> [Element] {
        return self.uniqued(comparator: ==)
    }
}

마지막으로 다음과 같이 uniqued의 키패스 버전을 추가할 수 있습니다.

extension Sequence {

    /// Returns the sequence with duplicate elements removed, performing the comparison using the property at
    /// the supplied keypath.
    ///
    /// i.e.
    ///
    /// ```
    /// [
    ///   MyStruct(value: "Hello"),
    ///   MyStruct(value: "Hello"),
    ///   MyStruct(value: "World")
    ///  ].uniqued(\.value)
    /// ```
    /// would result in
    ///
    /// ```
    /// [
    ///   MyStruct(value: "Hello"),
    ///   MyStruct(value: "World")
    /// ]
    /// ```
    ///
    /// - note: Taken from stackoverflow.com/a/46354989/3141234
    ///
    func uniqued<T: Equatable>(_ keyPath: KeyPath<Element, T>) -> [Element] {
        self.uniqued { $0[keyPath: keyPath] == $1[keyPath: keyPath] }
    }
}

할 수 이이 your your your your your your your 에 따라 적절한 것을 합니다.재빠르다Iterator.Elementdiscloss.discloss.


El Capitan의 경우 다음과 같은 여러 키 경로를 포함하도록 이 메서드를 확장할 수 있습니다.

    /// Returns the sequence with duplicate elements removed, performing the comparison using the property at
    /// the supplied keypaths.
    ///
    /// i.e.
    ///
    /// ```
    /// [
    ///   MyStruct(value1: "Hello", value2: "Paula"),
    ///   MyStruct(value1: "Hello", value2: "Paula"),
    ///   MyStruct(value1: "Hello", value2: "Bean"),
    ///   MyStruct(value1: "World", value2: "Sigh")
    ///  ].uniqued(\.value1, \.value2)
    /// ```
    /// would result in
    ///
    /// ```
    /// [
    ///   MyStruct(value1: "Hello", value2: "Paula"),
    ///   MyStruct(value1: "Hello", value2: "Bean"),
    ///   MyStruct(value1: "World", value2: "Sigh")
    /// ]
    /// ```
    ///
    /// - note: Taken from stackoverflow.com/a/46354989/3141234
    ///
    func uniqued<T: Equatable, U: Equatable>(_ keyPath1: KeyPath<Element, T>, _ keyPath2: KeyPath<Element, U>) -> [Element] {
        self.uniqued {
            $0[keyPath: keyPath1] == $1[keyPath: keyPath1] && $0[keyPath: keyPath2] == $1[keyPath: keyPath2]
        }
    }

게 것 같아self.uniqued.

기능하는 프로그래머처럼 생각하십시오:)

요소가 이미 발생했는지 여부에 따라 목록을 필터링하려면 인덱스가 필요합니다.하시면 됩니다.enumeratedmap을 사용하다

let unique = myArray
    .enumerated()
    .filter{ myArray.firstIndex(of: $0.1) == $0.0 }
    .map{ $0.1 }

이렇게 하면 순서가 보장됩니다.인 '어느 정도'가 것 같습니다.Array(Set(myArray))하다


업데이트: 효율성 및 정확성에 대한 주의사항

몇몇 사람들이 효율성에 대해 언급하고 있다.입니다만, 이 더 는 논란의 Array(Set(array)).

, 느리다, 느리다, , 느리다, 느리다, 느리다, 느리다, 느리다, 느리다, 느리다, 느리다, 느리다, 느리다.Array(Set(array))코멘트에 기재되어 있듯이 순서를 유지하고 해시할 수 없는 요소에서 동작합니다.

다만, @Alain T의 메서드는 순서를 유지하는 것과 동시에, 보다 고속입니다.따라서 요소 유형이 해시 가능하지 않거나 라이너가 하나만 필요한 경우가 아니라면 해당 솔루션을 사용하는 것이 좋습니다.

다음은 릴리스 모드의 Xcode 11.3.1(Swift 5.1)에서 MacBook Pro(2014)에 대한 몇 가지 테스트입니다.

프로파일러 함수와 비교할 수 있는2가지 방법:

func printTimeElapsed(title:String, operation:()->()) {
    var totalTime = 0.0
    for _ in (0..<1000) {
        let startTime = CFAbsoluteTimeGetCurrent()
        operation()
        let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
        totalTime += timeElapsed
    }
    let meanTime = totalTime / 1000
    print("Mean time for \(title): \(meanTime) s")
}

func method1<T: Hashable>(_ array: Array<T>) -> Array<T> {
    return Array(Set(array))
}

func method2<T: Equatable>(_ array: Array<T>) -> Array<T>{
    return array
    .enumerated()
    .filter{ array.firstIndex(of: $0.1) == $0.0 }
    .map{ $0.1 }
}

// Alain T.'s answer (adapted)
func method3<T: Hashable>(_ array: Array<T>) -> Array<T> {
    var uniqueKeys = Set<T>()
    return array.filter{uniqueKeys.insert($0).inserted}
}

또한 다음과 같은 몇 가지 테스트 입력이 있습니다.

func randomString(_ length: Int) -> String {
  let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  return String((0..<length).map{ _ in letters.randomElement()! })
}

let shortIntList = (0..<100).map{_ in Int.random(in: 0..<100) }
let longIntList = (0..<10000).map{_ in Int.random(in: 0..<10000) }
let longIntListManyRepetitions = (0..<10000).map{_ in Int.random(in: 0..<100) }
let longStringList = (0..<10000).map{_ in randomString(1000)}
let longMegaStringList = (0..<10000).map{_ in randomString(10000)}

출력으로 제공:

Mean time for method1 on shortIntList: 2.7358531951904296e-06 s
Mean time for method2 on shortIntList: 4.910230636596679e-06 s
Mean time for method3 on shortIntList: 6.417632102966309e-06 s
Mean time for method1 on longIntList: 0.0002518167495727539 s
Mean time for method2 on longIntList: 0.021718120217323302 s
Mean time for method3 on longIntList: 0.0005312927961349487 s
Mean time for method1 on longIntListManyRepetitions: 0.00014377200603485108 s
Mean time for method2 on longIntListManyRepetitions: 0.0007293639183044434 s
Mean time for method3 on longIntListManyRepetitions: 0.0001843773126602173 s
Mean time for method1 on longStringList: 0.007168249964714051 s
Mean time for method2 on longStringList: 0.9114790915250778 s
Mean time for method3 on longStringList: 0.015888616919517515 s
Mean time for method1 on longMegaStringList: 0.0525397013425827 s
Mean time for method2 on longMegaStringList: 1.111266262292862 s
Mean time for method3 on longMegaStringList: 0.11214958941936493 s

확장자를 쓸 필요가 없습니다.

애플이 드디어 도입했습니다.uniqued()알고리즘 패키지에 메서드가 포함되어 있습니다.다음을 준수하는 유형에서 사용할 수 있습니다.Sequence프로토콜입니다.

import Algorithms

let numbers = [1, 2, 3, 3, 2, 3, 3, 2, 2, 2, 1]
print(numbers.uniqued()) // prints [1, 2, 3]

자세한 것은, https://github.com/apple/swift-algorithms/blob/main/Guides/Unique.md 를 참조해 주세요.

어레이에서 중복을 제거하기 위한 Swift 3.0 솔루션 1개 추가.이 솔루션은 이미 다음에서 제안한 많은 다른 솔루션보다 개선되었습니다.

  • 입력 배열에서 요소의 순서 유지
  • 선형 복잡도 O(n): 싱글 패스 필터 O(n) + 세트 삽입 O(1)

지정된 정수 배열:

let numberArray = [10, 1, 2, 3, 2, 1, 15, 4, 5, 6, 7, 3, 2, 12, 2, 5, 5, 6, 10, 7, 8, 3, 3, 45, 5, 15, 6, 7, 8, 7]

기능 코드:

func orderedSet<T: Hashable>(array: Array<T>) -> Array<T> {
    var unique = Set<T>()
    return array.filter { element in
        return unique.insert(element).inserted
    }
}

orderedSet(array: numberArray)  // [10, 1, 2, 3, 15, 4, 5, 6, 7, 12, 8, 45]

어레이 확장 코드:

extension Array where Element:Hashable {
    var orderedSet: Array {
        var unique = Set<Element>()
        return filter { element in
            return unique.insert(element).inserted
        }
    }
}

numberArray.orderedSet // [10, 1, 2, 3, 15, 4, 5, 6, 7, 12, 8, 45]

는 반환된 합니다.insertSet에 의해 실행됩니다.O(1)는 항목이 삽입되었는지 또는 이미 세트에 존재하는지 여부를 나타내는 태플을 반환합니다.

되어 있는 , ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」filter최종 결과에서 제외됩니다.

변수가 아닌 불변의 유형을 사용하는 대체 솔루션(최적이 아닌 경우):

func deleteDuplicates<S: ExtensibleCollectionType where S.Generator.Element: Equatable>(seq:S)-> S {
    let s = reduce(seq, S()){
        ac, x in contains(ac,x) ? ac : ac + [x]
    }
    return s
}

Jean-Pilippe의 필수 접근 방식과 기능적 접근 방식을 대조하기 위해 포함되어 있습니다.

또한 이 기능은 배열뿐만 아니라 문자열에도 사용할 수 있습니다!

편집: 이 답변은 2014년에 Swift 1.0용으로 작성되었습니다(이전).SetSwift 가능 시간으로 됩니다.해시 가능한 적합성과 2차 시간 실행이 필요하지 않습니다.

스위프트 5

extension Sequence where Element: Hashable {
    func unique() -> [Element] {
        NSOrderedSet(array: self as! [Any]).array as! [Element]
    }
}

스위프트 2

uniq 함수 응답:

func uniq<S: SequenceType, E: Hashable where E==S.Generator.Element>(source: S) -> [E] {
    var seen: [E:Bool] = [:]
    return source.filter({ (v) -> Bool in
        return seen.updateValue(true, forKey: v) == nil
    })
}

용도:

var test = [1,2,3,4,5,6,7,8,9,9,9,9,9,9]
print(uniq(test)) //1,2,3,4,5,6,7,8,9

Swift 4.x:

extension Sequence where Iterator.Element: Hashable {
  func unique() -> [Iterator.Element] {
    return Array(Set<Iterator.Element>(self))
  }

  func uniqueOrdered() -> [Iterator.Element] {
    return reduce([Iterator.Element]()) { $0.contains($1) ? $0 : $0 + [$1] }
  }
}

사용방법:

["Ljubljana", "London", "Los Angeles", "Ljubljana"].unique()

또는

["Ljubljana", "London", "Los Angeles", "Ljubljana"].uniqueOrdered()

Swift 5의 경우

 var array: [String] =  ["Aman", "Sumit", "Aman", "Sumit", "Mohan", "Mohan", "Amit"]

 let uniq = Array(Set(array))
 print(uniq)

출력은 다음과 같습니다.

 ["Sumit", "Mohan", "Amit", "Aman"]

요소가 해시 가능하지도 비교 가능하지도 않은 배열(복잡한 객체, 사전 또는 구조 등)의 경우 이 확장을 통해 중복을 제거할 수 있습니다.

extension Array
{
   func filterDuplicate<T:Hashable>(_ keyValue:(Element)->T) -> [Element]
   {
      var uniqueKeys = Set<T>()
      return filter{uniqueKeys.insert(keyValue($0)).inserted}
   }

   func filterDuplicate<T>(_ keyValue:(Element)->T) -> [Element]
   { 
      return filterDuplicate{"\(keyValue($0))"}
   }
}

// example usage: (for a unique combination of attributes):

peopleArray = peopleArray.filterDuplicate{ ($0.name, $0.age, $0.sex) }

or...

peopleArray = peopleArray.filterDuplicate{ "\(($0.name, $0.age, $0.sex))" }

해시 가능한 값을 만들 필요가 없으며 고유성을 위해 여러 필드 조합을 사용할 수 있습니다.

주의: 보다 견고한 접근방식은 아래 코멘트에서 Cour가 제안한 솔루션을 참조하십시오.

stackoverflow.com/a/55684308/1033581

[편집] Swift 4 대체품

Swift 4.2에서는 Hasher 클래스를 사용하여 해시를 훨씬 쉽게 작성할 수 있습니다.위의 확장을 변경하여 이를 활용할 수 있습니다.

extension Array
{
    func filterDuplicate(_ keyValue:((AnyHashable...)->AnyHashable,Element)->AnyHashable) -> [Element]
    {
        func makeHash(_ params:AnyHashable ...) -> AnyHashable
        { 
           var hash = Hasher()
           params.forEach{ hash.combine($0) }
           return hash.finalize()
        }  
        var uniqueKeys = Set<AnyHashable>()
        return filter{uniqueKeys.insert(keyValue(makeHash,$0)).inserted}     
    }
}

closure는 변수 개수의 값을 해시하는 함수를 포함하는 추가 파라미터를 수신하기 때문에 호출 구문은 조금 다릅니다(개별 해시 가능).

peopleArray = peopleArray.filterDuplicate{ $0($1.name, $1.age, $1.sex) } 

또한 단일 고유성 값($1을 사용하고 $0을 무시함)으로도 작동합니다.

peopleArray = peopleArray.filterDuplicate{ $1.name } 

WWDC 2021에서 언급한 바와 같이 Swift는 커뮤니티에서 개발한 알고리즘, 컬렉션 및 숫자 패키지를 보유하고 있습니다.에는 「」가 있습니다.uniqued()알고리즘.

이것들은 아직 Swift Standard 라이브러리의 일부가 아닙니다.현재 Apple의 Github 페이지에서 다운로드하거나 Swift Package Manager를 통해 설치할 수 있습니다.

WWDC 비디오:

https://developer.apple.com/videos/play/wwdc2021/10256/

Github 페이지:

https://github.com/apple/swift-algorithms

uniqued() ★★★★★★★★★★★★★★★★★」uniqued(on:)★★★★

https://github.com/apple/swift-algorithms/blob/main/Guides/Unique.md

  1. 먼저 어레이의 모든 요소를 NSOrenderedSet에 추가합니다.
  2. 어레이내의 모든 중복이 삭제됩니다.
  3. 다시 이 순서 집합을 배열로 변환합니다.

완료...

let array = [1,1,1,1,2,2,2,2,4,6,8]

let orderedSet : NSOrderedSet = NSOrderedSet(array: array)

let arrayWithoutDuplicates : NSArray = orderedSet.array as NSArray

array Without Duplicates 출력 - [1, 2, 4, 6, 8]

세트 컬렉션을 직접 사용하여 중복을 제거한 후 어레이에 다시 캐스트할 수 있습니다.

var myArray = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
var mySet = Set<Int>(myArray)

myArray = Array(mySet) // [2, 4, 60, 6, 15, 24, 1]

그러면 어레이를 원하는 대로 주문할 수 있습니다.

myArray.sort{$0 < $1} // [1, 2, 4, 6, 15, 24, 60]

값을 정렬해야 하는 경우 이 방법이 작동합니다(Swift 4).

let sortedValues = Array(Set(array)).sorted()

여기 다음과 같은 해결책이 있습니다.

  • " " " 를 하지 않습니다.NS
  • 「 」를 사용하면, 꽤입니다.O(n)
  • 간결하다
  • 요소 순서 유지
extension Array where Element: Hashable {

    var uniqueValues: [Element] {
        var allowed = Set(self)
        return compactMap { allowed.remove($0) }
    }
}

Airspeed Velocity의 원래 답변에 기반한 것으로 보이는 후행 폐쇄 및 속기 인수 이름을 사용하여 Daniel Krom의 Swift 2 답변의 약간 간결한 구문 버전:

func uniq<S: SequenceType, E: Hashable where E == S.Generator.Element>(source: S) -> [E] {
  var seen = [E: Bool]()
  return source.filter { seen.updateValue(true, forKey: $0) == nil }
}

에서 할 수 예uniq(_:) 안 된다).Hashable즉, 「」입니다.Equatable, 냐냐Hashable를 확장하다Equatable

func ==(lhs: SomeCustomType, rhs: SomeCustomType) -> Bool {
  return lhs.id == rhs.id // && lhs.someOtherEquatableProperty == rhs.someOtherEquatableProperty
}

struct SomeCustomType {

  let id: Int

  // ...

}

extension SomeCustomType: Hashable {

  var hashValue: Int {
    return id
  }

}

위 코드에서는...

id== , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , .Equatable 타입을 )Equatable예를 들어 다음과 같이 입력합니다.someMethodThatReturnsAnEquatableType()여기서 "는 동등성 체크를 확장합니다.someOtherEquatableProperty의 또 입니다.Equatable, 타입을 있습니다)Equatable라고 입력합니다

id에서 되고 있는와 같이hashValueproperty(「」에 )Hashable는 임의의 ( ), ( ), ( ), ( ), ( ), ( ), ( ), ( ), ( ), ( ), ( ), ( )입니다.Hashable)Equatable ""("")을 )Hashable라고 입력합니다

「」의 예uniq(_:):

var someCustomTypes = [SomeCustomType(id: 1), SomeCustomType(id: 2), SomeCustomType(id: 3), SomeCustomType(id: 1)]

print(someCustomTypes.count) // 4

someCustomTypes = uniq(someCustomTypes)

print(someCustomTypes.count) // 3

여기에서는 오브젝트의 O(n) 솔루션을 몇 가지 실시했습니다.몇 줄의 해결책은 아니지만...

struct DistinctWrapper <T>: Hashable {
    var underlyingObject: T
    var distinctAttribute: String
    var hashValue: Int {
        return distinctAttribute.hashValue
    }
}
func distinct<S : SequenceType, T where S.Generator.Element == T>(source: S,
                                                                distinctAttribute: (T) -> String,
                                                                resolution: (T, T) -> T) -> [T] {
    let wrappers: [DistinctWrapper<T>] = source.map({
        return DistinctWrapper(underlyingObject: $0, distinctAttribute: distinctAttribute($0))
    })
    var added = Set<DistinctWrapper<T>>()
    for wrapper in wrappers {
        if let indexOfExisting = added.indexOf(wrapper) {
            let old = added[indexOfExisting]
            let winner = resolution(old.underlyingObject, wrapper.underlyingObject)
            added.insert(DistinctWrapper(underlyingObject: winner, distinctAttribute: distinctAttribute(winner)))
        } else {
            added.insert(wrapper)
        }
    }
    return Array(added).map( { return $0.underlyingObject } )
}
func == <T>(lhs: DistinctWrapper<T>, rhs: DistinctWrapper<T>) -> Bool {
    return lhs.hashValue == rhs.hashValue
}

// tests
// case : perhaps we want to get distinct addressbook list which may contain duplicated contacts like Irma and Irma Burgess with same phone numbers
// solution : definitely we want to exclude Irma and keep Irma Burgess
class Person {
    var name: String
    var phoneNumber: String
    init(_ name: String, _ phoneNumber: String) {
        self.name = name
        self.phoneNumber = phoneNumber
    }
}

let persons: [Person] = [Person("Irma Burgess", "11-22-33"), Person("Lester Davidson", "44-66-22"), Person("Irma", "11-22-33")]
let distinctPersons = distinct(persons,
    distinctAttribute: { (person: Person) -> String in
        return person.phoneNumber
    },
    resolution:
    { (p1, p2) -> Person in
        return p1.name.characters.count > p2.name.characters.count ? p1 : p2
    }
)
// distinctPersons contains ("Irma Burgess", "11-22-33") and ("Lester Davidson", "44-66-22")

@Jean-Philippe Pellet의 답변을 사용하여 요소의 순서를 유지하면서 어레이에 대해 세트와 같은 작업을 수행하는 어레이 확장을 만들었습니다.

/// Extensions for performing set-like operations on lists, maintaining order
extension Array where Element: Hashable {
  func unique() -> [Element] {
    var seen: [Element:Bool] = [:]
    return self.filter({ seen.updateValue(true, forKey: $0) == nil })
  }

  func subtract(takeAway: [Element]) -> [Element] {
    let set = Set(takeAway)
    return self.filter({ !set.contains($0) })
  }

  func intersect(with: [Element]) -> [Element] {
    let set = Set(with)
    return self.filter({ set.contains($0) })
  }
}

이것은 매우 간단하고 편리한 구현입니다.동등한 요소를 가진 배열 확장의 계산된 속성입니다.

extension Array where Element: Equatable {
    /// Array containing only _unique_ elements.
    var unique: [Element] {
        var result: [Element] = []
        for element in self {
            if !result.contains(element) {
                result.append(element)
            }
        }

        return result
    }
}
func removeDublicate (ab: [Int]) -> [Int] {
var answer1:[Int] = []
for i in ab {
    if !answer1.contains(i) {
        answer1.append(i)
    }}
return answer1
}

사용방법:

let f = removeDublicate(ab: [1,2,2])
print(f)

스위프트 3 / 스위프트 4 / 스위프트 5

순서에 영향을 주지 않고 어레이 중복을 생략하는 라인 코드는 1개뿐입니다.

let filteredArr = Array(NSOrderedSet(array: yourArray))

언급URL : https://stackoverflow.com/questions/25738817/removing-duplicate-elements-from-an-array-in-swift