如何在Swift中用一个数组减去另一个数组?

nkcskrwz  于 2023-01-16  发布在  Swift
关注(0)|答案(6)|浏览(307)

我想用array2减去array1示例:

var array1 = ["the", "people", "prefer", "to", "go", "to", "the","sun","beach"]

var array2 = ["the", "people", "prefer", "go", "to", "the", "moon","beach"]

我想要输出:

["to","sun"]

我目前正在尝试的:

let reuslt = array1.filter { ! array2.contains($0) }

输出:

["sun"]

它正在检查是否包含匹配项,如果匹配,则删除所有项,但我想一对一地删除。

a1o7rhls

a1o7rhls1#

就像在大脑中那样在计算机上执行,循环array2(而不是array1),对于array2的每个元素,如果该元素在array1中有firstIndex,则从array1中删除该索引处的元素。

for word in array2 {
    if let index = array1.firstIndex(of: word) {
        array1.remove(at: index)
    }
}
fykwrbwg

fykwrbwg2#

实际上你要做的就是这个for循环

for item2 in array2 {
    for i in 0..<array1.count {
        if item2 == array1[i] {
            array1.remove(at: i)
            break
        }
    }
}

过滤器的工作方式与此完全相同,只是它不会在第一个项目上中断,而是继续删除所有项目。
你也可以把它放到一个像这样的一行程序中,用map代替filter:array2.map({guard let i = array1.firstIndex(of: $0) else {return}; array1.remove(at: i)})

0ve6wy6x

0ve6wy6x3#

和上面的答案一样,循环包含findIndex和remove from array也是可以的。
但在其他情况下,我认为如果数组太大,firstIndex(of:)和remove(at:)的复杂性会导致时间和CPU太多-设备的热量也会增加很多。您可以使用字典来最小化它。
这是另一种方法:

func findTheDiff(_ compareArr: [String], _ desArr: [String]) -> [String] {
    var resultArr : [String] = []
    
    var dict : [String: Int] = [:]
    
    for word in compareArr {
        if dict[word] == nil {
            dict[word] = 1
        } else {
            dict[word] = dict[word]! + 1
        }
    }
    
    for checkWord in desArr {
        if dict[checkWord] != nil && dict[checkWord]! > 0 {
            dict[checkWord] = dict[checkWord]! - 1
            continue
        }
        
        resultArr.append(checkWord)
    }
    
    return resultArr
}

用法:

var array1 = ["the", "people", "prefer", "to", "go", "to", "the","sun","beach"]

var array2 = ["the", "people", "prefer", "go", "to", "the", "moon","beach"]
        
var result = self.findTheDiff(array2, array1)
print(result) // ["to", "sun"]

您可以在下面找到firstIndex,remove(at:)的复杂性:https://developer.apple.com/documentation/swift/array/firstindex(of:)https://developer.apple.com/documentation/swift/array/remove(at:)-1p2pj

jum4pzuy

jum4pzuy4#

@Thang Phi的答案是正确的,这并没有什么不同,但它在抽象的层面上工作,结合了Swift尚未提供内置类型的"计数集"思想:

import OrderedCollections

public extension Sequence where Element: Hashable {
  /// A version of this sequence without the earliest occurrences of all `elementsToRemove`.
  ///
  /// If `elementsToRemove` contains multiple equivalent values,
  /// that many of the earliest occurrences will be filtered out.
  func filteringOutEarliestOccurrences(from elementsToRemove: some Sequence<Element>) -> some Sequence<Element> {
    var elementCounts = Dictionary(bucketing: elementsToRemove)
    return lazy.filter {
      do {
        try elementCounts.remove(countedSetElement: $0)
        return false
      } catch {
        return true
      }
    }
  }
}
public extension Dictionary where Value == Int {
  /// Create "buckets" from a sequence of keys,
  /// such as might be used for a histogram.
  /// - Note: This can be used for a "counted set".
  @inlinable init(bucketing unbucketedKeys: some Sequence<Key>) {
    self.init(zip(unbucketedKeys, 1), uniquingKeysWith: +)
  }

  /// Treating this dictionary as a "counted set", reduce the element's value by 1.
  /// - Throws: If `countedSetElement` is not a key.
  @inlinable mutating func remove(countedSetElement: Key) throws {
    guard let count = self[countedSetElement] else { throw AnyError() }
    self[countedSetElement] = count == 1 ? nil : count - 1
  }
}
/// `zip` a sequence with a single value, instead of another sequence.
@inlinable public func zip<Sequence: Swift.Sequence, Constant>(
  _ sequence: Sequence, _ constant: Constant
) -> some Swift.Sequence<(Sequence.Element, Constant)> {
  zip(sequence, **ModuleName**.sequence(constant))
}
/// An infinite sequence of a single value.
@inlinable public func sequence<Element>(_ element: Element) -> some Sequence<Element> {
  let getSelf: (Element) -> Element = \.self
  return sequence(first: element, next: getSelf)
}
/// A nondescript error.
public struct AnyError: Error & Equatable {
  public init() { }
}
zxlwwiss

zxlwwiss5#

你的例子在输出上看起来有点混乱/不完整。但是听起来你可以做这样的事情:

extension Array where Element: Hashable {
    func difference(from other: [Element]) -> [Element] {
        let thisSet = Set(self)
        let otherSet = Set(other)
        return Array(thisSet.symmetricDifference(otherSet))
    }
}

let names1 = ["the", "people", "prefer", "to", "go", "to", "the","sun","beach"]
let names2 = ["the", "people", "prefer", "go", "to", "the", "moon","beach"]
let difference = names1.difference(from: names2)

print(Array(difference)) // ["sun", "moon"]

当然,使用扩展可以使这些代码对项目中的所有数组都可用。由于我们将数组转换为集合,因此重复的代码会被删除,这在您的用例中可能是一个问题。
此阵列扩展取自:https://www.hackingwithswift.com/example-code/language/how-to-find-the-difference-between-two-arrays所有事物的重要资源,尤其是SwiftUI。

aor9mmx1

aor9mmx16#

适用于Equatable类型(包括String)的简单减法。

extension Array where Element: Equatable {
    func subtracting(_ array: Array<Element>) -> Array<Element> {
        var result: Array<Element> = []
        var toSub = array
        
        for i in self {
            if let index = toSub.firstIndex(of: i) {
                toSub.remove(at: index)
                continue
            }
            else {
                result.append(i)
            }
        }
        return result
    }
}

let first = [1, 1, 2, 3, 3, 5, 6, 7, 7]
let second = [2, 2, 3, 4, 4, 5, 5, 6]
let result = first.subtracting(second)

//print result 
//[1, 1, 3, 7, 7]

相关问题