web-dev-qa-db-ja.com

Swift 2つの配列に同じ要素が含まれている場合、それらの要素が現れる順序に関係なくチェックインするにはどうすればよいですか?

2つの配列があるとしましょう...

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

これら2つの配列の比較の結果が真であり、次のことを望んでいます...

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

...虚偽である。 Swiftでそれをどのように達成できますか?両方の配列をセットに変換しようとしましたが、何らかの理由でSet()が配列に含まれる(通常は複製された)オブジェクトを削除し続けます。

任意の助けをいただければ幸いです。

37

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

70
Alexander Doloz

次のようなことができます:

  array1.sortInPlace()
  array2.sortInPlace()

  print(array1,array2)

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

元の配列を変更したくない場合は、

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

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

それらを比較する関数を作成します。

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

次に:

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

以下は、要素がComparableである必要はなく、Equatableのみであるソリューションです。ソートの答えよりもはるかに効率が悪いため、タイプを比較可能にできる場合は、それらのいずれかを使用してください。

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

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

このソリューションの主な利点は、他よりも少ないメモリを使用することです(常に2つの一時配列のみを作成します)。また、ElementComparableである必要はなく、Equatableである必要があります。

1
Roman Podymov

配列の要素がHashableに準拠している場合、バッグを使用してみることができます(各アイテムの量を登録したセットのようなものです)。ここでは、Dictionaryに基づいたこのデータ構造の簡易バージョンを使用します。この拡張機能は、Hashableの配列からバッグを作成するのに役立ちます。

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

次に、初期配列から2つのバッグを生成し、それらを比較する必要があります。この拡張機能でラップしました。

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

このソリューションは、Swift 4.2/Xcode 10でテストされました。現在のXcodeバージョンが10.0より前の場合、allSatisfy of ArraySliceの関数を見つけることができます- Xcode9to10Preparation 。CocoaPodsでこのライブラリをインストールできます。

1
Roman Podymov

Setを使用する

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

if (Set(array1) == Set(array2)) {
     //they are identical
}

SetHashableを実装するため、タスクはSetで動作するハッシュ関数を実装することです

0
yoAlex5