Swift'teki bir diziden yinelenen öğeleri kaldırma


252

Günümüzde Swift'te Set( yourArray )bir diziyi benzersiz kılmak için yazmanız yeterlidir . (Veya gerekirse sipariş edilen bir set.)

Bu mümkün olmadan önce nasıl yapıldı?


Aşağıdaki gibi görünen bir dizi olabilir:

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

Ya da, gerçekten, herhangi bir benzer tipte veri bölümleri dizisi. Yapmak istediğim şey, her bir özdeş öğeden sadece bir tanesinin olmasını sağlamak. Örneğin, yukarıdaki dizi şöyle olur:

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

2, 6 ve 15 nolu kopyaların, her bir özdeş öğeden sadece birinin bulunduğundan emin olmak için çıkarıldığına dikkat edin. Swift bunu kolayca yapmanın bir yolunu sunuyor mu yoksa bunu kendim mi yapmam gerekecek?


11
En kolay yolu diziyi bir dönüştürmek, NSSetNSSet sipariş NSOrderedSet tutmak gerekiyorsa, sırasız bir nesne koleksiyonudur.
Andrea

Kavşak fonksiyonunu bu sınıfta bulabileceğiniz gibi diziler için fonksiyonlarla kullanabilirsiniz: github.com/pNre/ExSwift/blob/master/ExSwift/Array.swift
Edwin Vermeer

Swift'in bir parçası değil ama Doları kullanıyorum. $.uniq(array) github.com/ankurp/Dollar#uniq---uniq
Andy

Muhtemelen en zarif, en akıllı ve en hızlı cevap mxcl'nin aşağıdaki cevabı ile sağlanır . Bu da düzeni korumaya yardımcı olur
Honey

1
Neden sadece SetSwift'ten kullanmıyorsun ? Sırasız ve benzersiz öğelerin bir listesini sağlayabileceksiniz.
1919'da TibiaZ

Yanıtlar:


133

Kendinizi yuvarlayabilirsiniz, örneğin bunun gibi ( Set ile Swift 1.2 için güncellendi ):

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]

Swift 3 sürümü:

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
}

Ve bunun bir uzantısı olarak 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
    }
}

12
Bu fonksiyonun gövdesini şu şekilde de uygulayabilirsinizvar addedDict = [T:Bool](); return filter(source) { addedDict(true, forKey: $0) == nil }
Hava Hızı Hızı

1
@AirspeedVelocity: aradınız updateValue(true, forKey: $0)...yerineaddedDict(true, forKey: $0)...
Jawwad

1
Hata! Üzgünüm yöntemi yanlışlıkla! Söylediğin return filter(source) { addedDict.updateValue(true, forKey: $0) == nil }gibi olmalı .
Hava Hızı Hızı

21
Dikkat etmeniz gereken bir nokta: Performanslarına güvenebileceğinize kadar bu gibi basit işlevler için performansı tartışmaktan kaçının; bu noktada yapmanız gereken tek şey kıyaslamadır. Varsayımlardan dolayı sık sık sürdürülemeyen kod veya daha az performans kodu gördüm. :) Ayrıca, bu muhtemelen kavramak daha kolay:let uniques = Array(Set(vals))
Blixt

11
@Blixt Kabul etti. Bir kez daha, burada avantaj, orijinal dizinin elemanlarının sırasına saygı duymaktır.
Jean-Philippe Pellet

493

Bir sete dönüşebilir ve bir diziye tekrar kolayca geri dönebilirsiniz:

let unique = Array(Set(originals))

Dizinin orijinal sırasını koruyacağı garanti edilmez.


37
Dizinin orijinal sırasını korurken bir set kullanmanın bir yolu var mı?
Crashalot

6
@Crashalot Cevabımı görün.
Jean-Philippe Pellet

5
Nesneleri belirli bir özellik tarafından benzersiz tutmanız gerekiyorsa, yalnızca Array-> Set-> Array dönüşümü
Fawkes

2
Güzel!! Bu çözümün zaman karmaşıklığı nedir?
JW.ZG

2
Elemanları eğer başarısız originalsdeğildir Hashable; bir Kümeye yalnızca Hashableveri türleri eklenebilir, ancak bir diziye herhangi bir veri türü eklenebilir.
Mecki

69

Burada birçok yanıt var, ancak Swift 2 ve üstü için uygun olan bu basit uzantıyı kaçırdım:

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

Süper basit yapar. Bu şekilde çağrılabilir:

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

Özelliklere göre filtreleme

Bir diziyi özelliklere göre filtrelemek için şu yöntemi kullanabilirsiniz:

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

Aşağıdaki gibi arayabilirsiniz:

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

@Antoine Özellik uzantısına dayalı Filtreleme için teşekkür ederiz. Gerçekten faydalı. Ama lütfen nasıl çalıştığını açıklayabilir misiniz? Benim için anlamak çok zor. Teşekkür ederim
Mostafa Mohamed Raafat

Hızlı 3 Güncellemeler: işlev filterDuplicates (_ includeElement: (_ sol eksen: Eleman, _ RHS: Eleman) -> BOOL) -> [Element] {
cbartel

Bu cevabın ( extension Array where Element: Equatable) ilk kısmı daha güçlü bir çözüm ( ) sunan stackoverflow.com/a/36048862/1033581 ile değiştiriliyor extension Sequence where Iterator.Element: Equatable.
Junur

7
Bu, O(n²)büyük diziler için gerçekten kötü olan zaman performansına sahip olacaktır .
Duncan C

Şimdiye kadar görülen unsurları takip etmek, bu korkunç O(n²)karmaşıklığı geri getirmek için bir set kullanmalısınızO(n)
Alexander - Reinstate Monica

63

Swift 3.0

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

1
let uniqueOrderedNames = Dizi (NSOrderedSet (dizi: kullanıcıAdları)) olarak! [String] Eğer herhangi biri değil, String dizisi varsa
Zaporozhchenko Oleksandr

Elemanları eğer başarısız arraydeğildir Hashable; bir Kümeye yalnızca Hashableveri türleri eklenebilir, ancak bir diziye herhangi bir veri türü eklenebilir.
Mecki

Swift 5.1b5'te test edilen, öğelerin Hashable ve sipariş tutma isteği olduğu göz önüne alındığında, NSOrderedSet (dizi: dizi) .dizisi, filtreli bir set kullanılarak saf hızlı işlevden () benzersiz bir şekilde daha hızlıdır. 13 benzersiz değerle sonuçlanan 5100 dizeyle test ettim.
dlemex

62

Her iki uzantıyı da kodunuza koyarsanız, daha hızlı Hashablesürüm mümkün olduğunda kullanılır ve Equatablesürüm yedek olarak kullanılır.

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)
      }
    }
  }
}

Sipariş önemli değilse, her zaman bu Set başlatıcıyı kullanabilirsiniz .


tamam anladım. benim dizi yapıları bir dizi olduğundan onu aramak mümkün değildi ... nasıl benim durumumda ele? 20 farklı değişkenin yapısı, string ve [string]
David Seek

@David Seek Sıkı yıkanabilir veya eşitlenebilir hale getirmemiş gibi görünüyorsunuz. Bu doğru mu?
Jessy

1
@DavidSeek bunu beğendi, uniqueArray = nonUniqueArray.uniqueElements
Mert Çelik

evet endişelenme. hemen çalışmasını sağladım. neredeyse 2 yıl oldu: P
David Seek

Bu, O(n²)büyük diziler için gerçekten kötü olan zaman performansına sahip olacaktır .
Duncan C

44

Swift 4 veya daha yenisini düzenle / güncelle

Ayrıca, RangeReplaceableCollectionprotokolün StringProtocoltürlerle de kullanılmasına izin vermek için genişletebiliriz :

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"

Mutasyon yöntemi:

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

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

İçin Swift 3 tıklayın burada


1
Bunu beğendim, bir dizi sözlükle de çalışıyor!
DeyaEldeen

6
O (N ^ 2) kötü :(
Alexander - Monica'yı eski

1
@Alexander Leo Dabus uygulamanın yerini aldı reduce, bu yüzden şimdi karmaşıklık farklı.
Coeur

1
Sonuçlar ilginç. Hem 1 milyon benzersiz ürün hem de 8 milyon için filtre sürümü daha hızlıdır. Bununla birlikte, filtre tabanlı sürüm 8 milyon benzersiz öğe ( O(n)zaman içinde bir saç ) için 8.38x daha uzun sürer, burada flatmap tabanlı sürüm 1 milyondan 8 milyon benzersiz giriş için 7.47x daha uzun sürer, bu da flatmap tabanlı sürümün daha iyi ölçeklendiğini gösterir . Her nasılsa flatmap tabanlı sürüm O(n)zamandan biraz daha iyi yapar !
Duncan C

1
Aslında, dizide 64x daha fazla öğe ile testi çalıştırdığımda, flatmap tabanlı sürüm daha hızlı.
Duncan C

43

Hızlı 4

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

her girişimi insertde bir demet döndürür: (inserted: Bool, memberAfterInsert: Set.Element). Belgelere bakın .

Döndürülen değeri kullanmak, döngü veya başka bir işlem yapmamıza yardımcı olur.


7
Basit profillemeden sonra, bu yöntem gerçekten hızlıdır. Küçültme (_: _ :), hatta azaltma (içine: _ :)
Kelvin,

3
@Kelvin Çünkü diğer algoritmalar öyleydi O(n^2)ve kimse fark etmedi.
Alexander - Monica'yı eski

@Kelvin bu cevap Eneko Alonso'nun cevabı + benim yorumumla aynı (16 Haziran 1717).
Cœur

27

Hızlı 4

Sipariş vermeye devam garantisi.

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

Bunu şimdi kullanıyorum, sadece kaldırmak için yöntem adını değiştirdimÇiftler :)
J. Doe

Bu çözüm kompakt sanırım, ama buna inanıyorum deanWombourne çözüm daha erken bir yıl olabilir yayınlanan biraz daha verimli bir daha reduce: genel olarak, gibi işlev yazmak için bütün projede sadece bir daha çizgi: var unique: [Iterator.Element] = []; for element in self where !unique.contains(element) { unique.append(element) }; return unique. Göreceli performansları henüz test etmediğimi itiraf ediyorum.
Cœur

3
Bu, O(n²)büyük diziler için gerçekten kötü olan zaman performansına sahip olacaktır .
Duncan C

@NickGaens Hayır değil, öyle O(n²). Bu konuda hızlı bir şey yok.
Alexander - Monica'yı

@ Cœur reduceya reduce(into:)da kritik bir fark yaratmaz . Bunu tekrar tekrar çağırmamak için yeniden yazmak containsÇOK daha büyük bir fark yaratacaktır.
Alexander - Monica'yı

16

İşte SequenceTypedizinin orijinal sırasını koruyan, ancak Array'ın yöntemindeki maliyeti önlemek için aramaları Setyapmak için a kullanan bir kategori .containsO(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 }
    }
}

Yıkanabilir veya Eşit Değilseniz, eşitlik kontrolünü yapmak için bir belirti iletebilirsiniz:

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

Eğer Hashable var, ama yoksa Şimdi, olan Equatable, bu yöntemi kullanabilirsiniz:

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: ==)
    }
}

Son olarak, benzersiz bir anahtar yol sürümünü şu şekilde ekleyebilirsiniz:

extension Sequence {

    /// Returns the sequence with duplicate elements removed, performing the comparison usinig 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] }
    }
}

Bunların ikisini de uygulamanıza yapıştırabilirsiniz, Swift dizinizin türüne bağlı olarak doğru olanı seçer Iterator.Element.


Heyyy sonunda O(n)çözümü olan biri . Bu arada "kontrol" ve "insert" set işlemlerini bir arada birleştirebilirsiniz. Bkz. Stackoverflow.com/a/46354989/3141234
Alexander - Yeniden Başla Monica

Oh, bu zeki :)
deanWombourne

15

Https://www.swiftbysundell.com/posts/the-power-of-key-paths-in-swift'ten esinlenerek , herhangi bir keyPath üzerindeki tekliği filtreleyebilen daha güçlü bir araç bildirebiliriz. Alexander'ın karmaşıklıkla ilgili çeşitli cevaplar hakkındaki yorumları sayesinde, aşağıdaki çözümler optimal olmalıdır.

Değişmeyen çözelti

Herhangi bir keyPath üzerinde tekliği filtreleyebilen bir işlevle genişletiyoruz:

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

Not: nesnenizin RangeReplaceableCollection ile uyumlu olmadığı, ancak Sekans ile uyumlu olduğu durumda, bu ek uzantıya sahip olabilirsiniz, ancak dönüş türü her zaman bir Array olur:

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

kullanım

Soruda olduğu gibi, elemanların kendileri için teklik istiyorsak, keyPath'i kullanırız \.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] */

Başka bir şey için teklik istiyorsak id(bir nesne koleksiyonunda olduğu gibi), seçtiğimiz keyPath'i kullanırız:

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}] */

Mutasyon çözümü

Herhangi bir keyPath üzerinde tekliği filtreleyebilen bir mutasyon işlevi ile uzanırız:

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

kullanım

Soruda olduğu gibi, elemanların kendileri için teklik istiyorsak, keyPath'i kullanırız \.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] */

Başka bir şey için teklik istiyorsak id(bir nesne koleksiyonunda olduğu gibi), seçtiğimiz keyPath'i kullanırız:

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}] */

1
Şimdi bu iyi bir uygulama! Ben sadece bu anahtar yolları kapanışlara dönüştürülebilir, böylece hem keyfi kod (kapanışlarda) hem de salt özellik bakmak (anahtar yolları üzerinden) desteklemek için bir kapatma arg kullanabilirsiniz. Yapacağım tek değişiklik keyPathvarsayılan olarak yapmaktır \.self, çünkü bu muhtemelen kullanım durumlarının çoğunluğudur.
Alexander - Monica'yı eski

1
@Alexander Ben varsayılan olarak denedim, ama sonra Elementher zaman yapmak gerekir Hashable. Varsayılan değere bir alternatif, parametresiz basit bir aşırı yük eklemektir:extension Sequence where Element: Hashable { func unique() { ... } }
Aprur

Ah evet, mantıklı!
Alexander - Monica'yı eski

1
Parlak ... basit ve en iyisi de 'esnek'. Teşekkürler.
BonanzaDriver

12

Alternatif (optimum değilse) den çözüm burada değişkenler yerine değişmez türleri kullanarak:

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-Pillippe'nin zorunlu yaklaşımını işlevsel bir yaklaşımla karşılaştırmak için dahil edilmiştir.

Bonus olarak bu işlev dizelerle olduğu gibi dizilerle de çalışır!

Edit: Bu cevap 2014 yılında Swift 1.0 (daha önce SetSwift kullanılabilir) için yazılmıştır . Yıkanabilir uyumluluk gerektirmez ve karesel zamanda çalışır.


8
Dikkat edin, bir tane yoktur, ancak bu ikinci dereceden zamanda çalışır - hem containsve dizi eki O (n) 'de çalışır. Rağmen sadece eşit, yıkanabilir değil gerektirir faydası vardır.
Hava Hızı Hızı

bu gerçekten karmaşık bir yazma şeklidir filter. O (n ^ 2) ( Hashableuyumluluk istemiyorsanız gereklidir ), ancak en azından bunu açıkça söylemelisiniz
Alexander - Reinstate Monica

10

hızlı 2

ile uniq fonksiyon cevap:

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
    })
}

kullanın:

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

BoolKodunuzu okur asla değer açıkçası, gereksiz olduğunu. Yerine bir Setkullanın Dictionaryve benim oyumu almak.
Nikolai Ruhe

10

Swift 5'te

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

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

Çıktı

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

2
Bu, zaten burada bulunan cevapların çoğunun bir tekrarıdır ve sıralamayı korumaz.
Alexander - Monica'yı eski

9

Bir diziden yinelenenleri kaldırmak için bir Swift 3.0 çözümü daha. Bu çözüm, şu anda önerilmiş olan diğer birçok çözümü geliştirir:

  • Giriş dizisindeki öğelerin sırasını koruma
  • Doğrusal karmaşıklık O (n): tek geçişli filtre O (n) + set yerleştirme O (1)

Tam sayı dizisi verildiğinde:

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]

Fonksiyonel kod:

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]

Dizi uzatma kodu:

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]

Bu kod tarafından döndürülen sonucu yararlanır insertilgili işlem Setüzerinde çalışır, O(1)ve madde eklenmesi durumunda gösteren getiri tuple veya zaten kümesinde mevcut ise.

Öğe filterkümedeyse, nihai sonuçtan hariç tutar.


1
Seçici olmamakla birlikte, ekleri ve üyelik testini elemanlar olduğu kadar çok kez gerçekleştireceksiniz, böylece maliyetlerini O (n) olarak saymalısınız. Bu 3xO (n) anlamına gelmez, çünkü bu O'lar ve filtreyle eşit maliyete sahip olmadığından O (n) 'nin eklenmesi portakallara elmalardır. Ayarlanmış işlemleri filtre maliyetinin O (1) parçası olarak değerlendirirsek, karmaşıklık yalnızca daha büyük bir "O" olsa da O (n) olur. Bunu sınıra kadar iterek, öğe kümede olduğunda eklemeleri de önleyebilirsiniz.
Alain T.

Sen kullanarak, doğru defer, iki kez set testi işlemi yapacağını ile bir kod containsile bir insert. Daha fazla okuma Swift belgeleri, ben inserteleman eklenmiş olup olmadığını gösteren bir tuple döndürür bulundu , bu yüzden containsonay kaldırma kodu basitleştirdim .
Eneko Alonso

2
Güzel. Uzantınız bunu yaparak optimum olabilirextension Sequence where Iterator.Element: Hashable { ... }
Cœur

@AlainT. Hayır! Hem insertve containssahip O(1)karmaşıklığı. O(1) + O(1) = O(1). Bu iki işlem daha sonra nsüreler yapılır (geçirilen kapama çağrısı başına bir filterkez, her öğe için bir kez çağrılır) Yani bir işlem giriş boyutundan bağımsız olarak sabit bir zaman alırsa, iki kez yapılması sabit bir zaman alır giriş boyutuna bakılmaksızın. Bunun toplam karmaşıklığı O(n).
Alexander - Monica'yı

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] }
  }
}

kullanımı:

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

veya

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

Bu O(n^2). Bunu yapma.
Alexander - Monica'yı

8

Hızlı 5

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

Karşılaştırmak için bir anahtar seçebilmem için bazı varyasyonlar yaptım. extension Sequence { // Returns distinct elements based on a key value. func distinct<key: Hashable>(by: ((_ el: Iterator.Element) -> key)) -> [Iterator.Element] { var existing = Set<key>() return self.filter { existing.insert(by($0)).inserted } } }
Marcelo de Aguiar

Kullandığınız Booltek değer olduğunda a kullanmaya gerek yoktur true. Bir "birim türü" (yalnızca bir olası değere sahip bir tür) elde ediyorsunuz. Swift'in birim tipi, Voidtek değeri olan ()(yani boş grup). Böylece sadece kullanabilirsiniz [T: Void]. Bunu yapmamalısınız, çünkü temelde sadece icat ettiniz Set. SetBunun yerine kullanın . Bkz. Stackoverflow.com/a/55684308/3141234 Lütfen bu yanıtı silin.
Alexander - Monica'yı eski

8

İşlevsel bir programcı gibi düşünün :)

Listeyi, öğenin zaten oluşup oluşmadığına göre filtrelemek için dizine ihtiyacınız vardır. enumeratedDizini almak ve mapdeğer listesine geri dönmek için tuşunu kullanabilirsiniz .

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

Bu emri garanti eder. Sipariş hakkında sakıncası yoksa, mevcut cevabı Array(Set(myArray))daha basit ve muhtemelen daha verimlidir.


GÜNCELLEME: Verimlilik ve doğruluk hakkında bazı notlar

Verimliliği birkaç kişi yorumladı. Kesinlikle doğru ve basit kod yazma okulundayım ve daha sonra darboğazları daha sonra anlamaya çalışıyorum, ancak bunun daha açık olup olmadığı tartışmalıdır Array(Set(array)).

Bu yöntem çok daha yavaştır Array(Set(array)). Yorumlarda belirtildiği gibi, düzeni korur ve Yıkanamayan öğeler üzerinde çalışır.

Bununla birlikte, @Alain T'nin yöntemi de düzeni korur ve çok daha hızlıdır. Öyleyse eleman tipiniz yıkanamaz veya hızlı bir astara ihtiyacınız yoksa, çözümlerine gitmenizi öneririm.

Sürüm modunda Xcode 11.3.1 (Swift 5.1) üzerinde bir MacBook Pro (2014) üzerinde yapılan birkaç test.

Profil oluşturma işlevi ve karşılaştırılacak iki yöntem:

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

Ve çok çeşitli test girdileri:

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)}

Çıktı olarak verir:

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

1
aksine Array(Set(myArray)), bu olmayan şeyler için çalışırHashable
Porter Child

1
... ve Array(Set(myArray))dizinizin sırasının aksine korunur.
Sander Saelmans

Bana en iyi cevap gibi görünüyor, en azından şu an Swift 5 zaten mevcut sürüm olduğunda.
oradyvan

Bu çok zarif bir çözüm; ne yazık ki, oldukça yavaş.
Colin Stark

1
@TimMB Mesajınızı yanlış okudum. Birinin kullandığı adaptasyonu gördüm lastIndex(of:). Bu durumda netlik vs optimizasyon noktasına tamamen katılmıyorum. Bu uygulamanın özellikle basit bir set tabanlı çözüme kıyasla özellikle net olduğunu düşünmüyorum. Her halükarda, bu kod bir genişletme işlevine çıkarılmalıdır. Bu algoritma, binlerce ila on binlerce gibi düşük bir giriş boyutunda bile kullanılamaz hale gelir. Bu tür veri setlerini bulmak zor değil, insanlar binlerce şarkı, dosya, kişi vb. Olabilir
Alexander - Reinstate Monica

6

Öğelerin Ne Yıkanabilir ne de Karşılaştırılabilir olmadığı diziler için (örn. Karmaşık nesneler, sözlükler veya yapılar), bu uzantı yinelenenleri kaldırmak için genelleştirilmiş bir yol sağlar:

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))" }

Hashable değerleri yapmakla uğraşmanıza gerek yok ve benzersizlik için farklı alan kombinasyonları kullanmanıza izin veriyor.

Not: Daha sağlam bir yaklaşım için lütfen aşağıdaki yorumlarda Coeur tarafından önerilen çözüme bakın.

stackoverflow.com/a/55684308/1033581

[EDIT] Swift 4 alternatifi

Swift 4.2 ile bir hash oluşturmak için Hasher sınıfını kullanabilirsiniz. Yukarıdaki uzantı, bundan yararlanmak için değiştirilebilir:

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

Çağıran sözdizimi biraz farklıdır, çünkü kapanış değişken sayıda değer hash etmek için bir işlev içeren ek bir parametre alır (ayrı ayrı yıkanabilir olmalıdır)

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

Ayrıca tek bir benzersiz değerle de çalışır (1 TL kullanarak ve 0 TL yok sayılır).

peopleArray = peopleArray.filterDuplicate{ $1.name } 

Bu, davranışına bağlı olarak rastgele sonuçlar verebilir "\()", çünkü size uyması gibi benzersiz değerler vermeyebilir Hashable. Örneğin, öğeleriniz Printableaynı döndürülerek uyuyorsa descriptionfiltrelemeniz başarısız olur.
Coeur

Kabul. İstenilen benzersizlik desenini üretecek alanların (veya formülün) seçiminde bunu dikkate almak gerekecektir. Birçok kullanım durumunda, bu, öğenin sınıfında veya yapısında herhangi bir değişiklik yapılmasını gerektirmeyen basit ve geçici bir çözüm sağlar.
Alain T.

2
@AlainT. Bunu gerçekten yapma. String'in amacı bazı getto ad-hoc anahtar üretme mekanizması olmak değildir. Sadece var Tolmayı kısıtlayın Hashable.
Alexander - Monica'yı

@Alexander Bu fikri yeni bir cevapta uyguladım: stackoverflow.com/a/55684308/1033581
Cœur

İstediğim gibi mükemmel cevap. Çok teşekkür ederim.
Hardik Thakkar

4

Yinelenenleri kaldırmak için doğrudan bir küme koleksiyonunu kullanabilir, ardından bir diziye geri gönderebilirsiniz

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]

Sonra dizinizi istediğiniz gibi sipariş edebilirsiniz

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

"Öyleyse dizinizi istediğiniz gibi sipariş edebilirsiniz" Ya orijinal diziyle aynı sıralamayı istersem? O kadar kolay değil.
Alexander - Monica'yı

3

Airspeed Velocity'nin orijinal cevabına dayanan görünen bir kapanış ve steno argüman adı kullanarak Daniel Krom'un Swift 2 cevabının biraz daha özlü sözdizimi sürümü :

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

İle birlikte kullanılabilir, özel bir türü uygulama örneği uniq(_:)(uygun olmalıdır ki Hashableböylece, ve Equatable, çünkü Hashableuzanır 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
  }

}

Yukarıdaki kodda ...

id, aşırı yüklenmesinde kullanıldığı gibi, ==herhangi bir Equatabletür (veya bir Equatabletür döndüren yöntem , ör someMethodThatReturnsAnEquatableType().) olabilir. Yorumlanan kod someOtherEquatableProperty, bir Equatabletürün başka bir özelliği olan eşitlik denetiminin genişletildiğini gösterir (ancak bir Equatabletür döndüren bir yöntem de olabilir ).

id, hashValuehesaplanan özellikte kullanıldığı gibi (uygun olması gerekir Hashable), herhangi bir Hashable(ve dolayısıyla Equatable) özellik (veya bir Hashabletür döndüren yöntem ) olabilir.

Kullanım örneği 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

Kullandığınız Booltek değer olduğunda a kullanmaya gerek yoktur true. Bir "birim türü" (yalnızca bir olası değere sahip bir tür) elde ediyorsunuz. Swift'in birim tipi, Voidtek değeri olan ()(yani boş grup). Böylece sadece kullanabilirsiniz [T: Void]. Bunu yapmamalısınız, çünkü temelde sadece icat ettiniz Set. SetBunun yerine kullanın . Bkz. Stackoverflow.com/a/55684308/3141234
Alexander - Monica'nın eski

3

Sıralama değerlerine ihtiyacınız varsa, bu işe yarar (Swift 4)

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


2
Bu durumda eleman sırasını kaybediyorsunuz.
Shmidt

Hiç de değil .sorted(), sonunda bunun için. Saygılarımızla.
Mauricio Chirino

@MauricioChirino Orijinal diziniz ise [2, 1, 1]? Bu çıkacağını [1, 2], bu sipariş değil: p
Alexander - Eski Monica

2
@MauricioChirino Hayır, değilim. Amaç, öğelerin benzersiz bir şekilde görünme sırasını korurken bir diziden yinelenen değerleri kaldırmaksa, bunu yapmaz. Çok açık karşı örnek [2, 1, 1]. Eşsiz öğelerin ilk görünümü, sırayla[2, 1] . Doğru cevap bu. Ama (yanlış) algoritması kullanılarak elde edersiniz [1, 2]ki, bir sınıflandırılır ancak değil doğru, orijinal, sırayla.
Alexander - Monica'yı Yeniden

2
Elemanları eğer başarısız arraydeğildir Hashable; bir Kümeye yalnızca Hashableveri türleri eklenebilir, ancak bir diziye herhangi bir veri türü eklenebilir.
Mecki

3

İşte bir çözüm

  • Eski NStür kullanmaz
  • İle oldukça hızlı O(n)
  • Özlü
  • Eleman sırasını korur
extension Array where Element: Hashable {

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

2

burada nesneler için bazı O (n) çözümü yaptım. Birkaç satırlık bir çözüm değil, ama ...

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")

1
Aksine bir kullanmaktan daha Setözel bir ile DistinctWrapper, bir kullanmalıdır Dictionarynesnelere distinctAttributes dan. Bu mantığı takip ettiğinizde, sonunda standart kütüphaneye yerleştirilmiş olan [ Dictionary.init(_:uniquingKeysWith:)] pastebin.com/w90pVe0p(https://developer.apple.com/documentation/… 'i kullanmaya başlayacaksınız . pastebin.com/w90pVe0p
Alexander - Monica'yı

2

@ Jean-Philippe Pellet'in cevabını kullandım ve elemanların sırasını korurken diziler üzerinde set benzeri işlemler yapan bir Array uzantısı yaptım.

/// 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) })
  }
}

Kullandığınız Booltek değer olduğunda a kullanmaya gerek yoktur true. Bir "birim türü" (yalnızca bir olası değere sahip bir tür) elde ediyorsunuz. Swift'in birim tipi, Voidtek değeri olan ()(yani boş grup). Böylece sadece kullanabilirsiniz [T: Void]. Bunu yapmamalısınız, çünkü temelde sadece icat ettiniz Set. SetBunun yerine kullanın . Bkz. Stackoverflow.com/a/55684308/3141234
Alexander - Monica'nın eski

2

Bu sadece çok basit ve kullanışlı bir uygulamadır. Eşit öğeler içeren bir Dizinin uzantısındaki hesaplanmış özellik.

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

1
Bu da O(n^2).
Alexander - Monica'yı

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

Kullanımı:

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

Bence bu en basit
Jack Rus

emri tutar ve istediğiniz diziyi verir
Jack Rus


2
  1. Önce bir dizinin tüm öğelerini NSOrderedSet öğesine ekleyin.
  2. Bu işlem dizinizdeki tüm kopyaları kaldıracaktır.
  3. Bu sıralı seti tekrar bir diziye dönüştürün.

Bitti ....

Misal

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

dizi çıktısıÇiftler - [1,2,4,6,8]


2

@ Jean-Philippe Pellet'in dizi uzantısı cevabına dayanan kısa süreli bir sürüm:

extension Array where Element: Hashable {

    var uniques: Array {
        var added = Set<Element>()
        return filter { element in
            defer { added.insert(element) }
            return !added.contains(element)
        }
    }
}

Bu, eleman başına iki karma işlemi yapar ve bu gereksizdir. insertöğenin zaten orada olup olmadığını veya ilk kez eklendiğini bildiren bir demet döndürür. stackoverflow.com/a/55684308/3141234 Lütfen bu yanıtı silin.
Alexander - Monica'yı eski

1

Her zaman bir Sözlük kullanabilirsiniz, çünkü bir Sözlük yalnızca benzersiz değerleri tutabilir. Örneğin:

var arrayOfDates: NSArray = ["15/04/01","15/04/01","15/04/02","15/04/02","15/04/03","15/04/03","15/04/03"]

var datesOnlyDict = NSMutableDictionary()
var x = Int()

for (x=0;x<(arrayOfDates.count);x++) {
    let date = arrayOfDates[x] as String
    datesOnlyDict.setValue("foo", forKey: date)
}

let uniqueDatesArray: NSArray = datesOnlyDict.allKeys // uniqueDatesArray = ["15/04/01", "15/04/03", "15/04/02"]

println(uniqueDatesArray.count)  // = 3

Gördüğünüz gibi, sonuçta ortaya çıkan dizi her zaman 'sırayla' olmayacaktır. Diziyi sıralamak / sıralamak istiyorsanız, şunu ekleyin:

var sortedArray = sorted(datesOnlyArray) {
(obj1, obj2) in

    let p1 = obj1 as String
    let p2 = obj2 as String
    return p1 < p2
}

println(sortedArray) // = ["15/04/01", "15/04/02", "15/04/03"]

.


1

En kolay yol, benzersiz öğeleri saklayan ve öğe sırasını koruyan NSOrderedSet kullanmaktır. Sevmek:

func removeDuplicates(from items: [Int]) -> [Int] {
    let uniqueItems = NSOrderedSet(array: items)
    return (uniqueItems.array as? [Int]) ?? []
}

let arr = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
removeDuplicates(from: arr)

Bu performansın buradaki daha iyi cevaplarla nasıl karşılaştırıldığını merak ediyorum. Karşılaştırdınız mı?
Alexander - Monica'yı eski
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.