web-dev-qa-db-fra.com

Comment vérifier dans Swift si deux tableaux contiennent les mêmes éléments, quel que soit leur ordre d'apparition?

Disons qu'il y a deux tableaux ...

var array1 = ["a", "b", "c"]
var array2 = ["b", "c", "a"]

J'aimerais que le résultat de la comparaison de ces deux tableaux soit vrai, et le suivant ...

var array1 = ["a", "b", "c"]
var array2 = ["b", "c", "a", "d"]

... être faux. Comment puis-je atteindre cet objectif dans Swift? J'ai essayé de convertir les deux tableaux en ensembles, mais pour une raison quelconque, Set () continue de supprimer certains objets (généralement dupliqués) contenus dans le tableau.

Toute aide serait appréciée.

31

Swift 3, 4

extension Array where Element: Comparable {
    func containsSameElements(as other: [Element]) -> Bool {
        return self.count == other.count && self.sorted() == other.sorted()
    }
}

// usage
let a: [Int] = [1, 2, 3, 3, 3]
let b: [Int] = [1, 3, 3, 3, 2]
let c: [Int] = [1, 2, 2, 3, 3, 3]

print(a.containsSameElements(as: b)) // true
print(a.containsSameElements(as: c)) // false

58
Alexander Doloz

vous pouvez faire quelque chose comme ça:

  array1.sortInPlace()
  array2.sortInPlace()

  print(array1,array2)

  if array1 == array2 {
    print("equal")
  } else {
  print("not equal") 
  }

et si vous ne voulez pas changer le tableau d'origine que nous pouvons faire 

 let sorted1 = array1.sort()
 let sorted2 = array2.sort()

  if sorted1 == sorted2 {
    print("equal")
  }else {
    print("not equal")
  }
6
Sahil

Créer une fonction pour les comparer:

func containSameElements(var firstArray firstArray: [String], var secondArray: [String]) -> Bool {
    if firstArray.count != secondArray.count {
        return false
    } else {
        firstArray.sortInPlace()
        secondArray.sortInPlace()
        return firstArray == secondArray
    }
}

Ensuite:

var array1 = ["a", "a", "b"]
var array2 = ["a", "b", "a"]

var array3 = ["a", "b", "c"]
var array4 = ["b", "c", "a", "d"]

print(containSameElements(firstArray: array1, secondArray: array2)) //true
print(containSameElements(firstArray: array3, secondArray: array4)) //false
print(array1) //["a", "a", "b"]
print(array2) //["a", "b", "a"]
print(array3) //["a", "b", "c"]
print(array4) //["b", "c", "a", "d"]
3
Khuong

Voici une solution qui n'exige pas que l'élément soit Comparable, mais seulement Equatable. Il est beaucoup moins efficace que les réponses de tri. Si votre type peut être comparé, utilisez l’une de celles-ci.

extension Array where Element: Equatable {
    func equalContents(to other: [Element]) -> Bool {
        guard self.count == other.count else {return false}
        for e in self{
          guard self.filter{$0==e}.count == other.filter{$0==e}.count else {
            return false
          }
        }
        return true
    }
}
2
Asa Zeren

Solution pour Swift 4.1/Xcode 9.4:

extension Array where Element: Equatable {
    func containSameElements(_ array: [Element]) -> Bool {
        var selfCopy = self
        var secondArrayCopy = array
        while let currentItem = selfCopy.popLast() {
            if let indexOfCurrentItem = secondArrayCopy.index(of: currentItem) {
                secondArrayCopy.remove(at: indexOfCurrentItem)
            } else {
                return false
            }
        }
        return secondArrayCopy.isEmpty
    }
}

Le principal avantage de cette solution est qu’elle utilise moins de mémoire que les autres (elle ne crée toujours que 2 tableaux temporaires). En outre, il n'est pas nécessaire que Element soit Comparable, mais simplement Equatable.

1
Roman Podymov

Si des éléments de vos tableaux sont conformes à Hashable, vous pouvez essayer d’utiliser le sac (c’est comme un ensemble avec l’enregistrement de la quantité de chaque article). Ici, je vais utiliser une version simplifiée de cette structure de données basée sur Dictionary. Cette extension permet de créer un sac à partir du tableau de Hashable:

extension Array where Element: Hashable {
    var asBag: [Element: Int] {
        return reduce(into: [:]) {
            $0.updateValue(($0[$1] ?? 0) + 1, forKey: $1)
        }
    }
}

Maintenant, vous devez générer 2 sacs à partir de tableaux initiaux et les comparer. Je l'ai enveloppé dans cette extension:

extension Array where Element: Hashable {
    func containSameElements(_ array: [Element]) -> Bool {
        let selfAsBag = asBag
        let arrayAsBag = array.asBag
        return selfAsBag.count == arrayAsBag.count && selfAsBag.allSatisfy {
            arrayAsBag[$0.key] == $0.value
        }
    }
}

Cette solution a été testée avec Swift 4.2/Xcode 10. Si votre version actuelle de Xcode est antérieure à 10.0, vous pouvez trouver la fonction allSatisfy de ArraySlice dans Xcode9to10Preparation . Vous pouvez installer cette bibliothèque avec CocoaPods.

1
Roman Podymov