iOS Swift:从另一个数组中删除数组元素

86

我有两个数组

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

我想从array1中删除array2的元素

Result ["b", "e"]
9个回答

132

@Antonio的解决方案更高效,但如果保持顺序很重要,那么这个解决方案也可以使用:

var array1 = ["a", "b", "c", "d", "e"]
let array2 = ["a", "c", "d"]
array1 = array1.filter { !array2.contains($0) }

喜欢这个方法。 - RoLYroLLs
好的回答!但是你知道如何用Obj-C编写这个吗?请帮我一下:) 谢谢 - Tung Fam
2
如果元素像在这种情况下一样是“可哈希”的,将array2先转换为Set可能更高效;这仍然会保留array1作为数组的顺序,但您可以在搜索集合上执行快速查找。 - Robert
4
为使其正常工作,您的对象还必须符合Equatable协议。如果不符合,您会在Swift 4.0中获得以下奇怪的错误消息:在filter函数内部的contains函数调用中缺少参数标签“where:”。 - C0D3
6
是的,你可以在contains里添加where:关键字,例如: array1 = array1.filter({ item in !array2.contains(where: { $0.id == item.id }) }) - Fede Cugliandolo
显示剩余2条评论

85

最简单的方法是将两个数组转换为集合,从第一个中减去第二个,将结果转换为数组并将其分配回array1

array1 = Array(Set(array1).subtracting(array2))

请注意,您的代码不是有效的 Swift 代码 - 您可以使用类型推断来声明并初始化两个数组,如下所示:
var array1 = ["a", "b", "c", "d", "e"]
var array2 = ["a", "c", "d"]

你能从一个集合中减去一个数组吗?这不需要这样做吗 array1 = Array(Set(array1).subtract(Set(array2))) (在从 array1 中减去 array2 之前先将 array2 转换为一个集合吗?) - Duncan C
@DuncanC:subtract方法(以及许多其他Set方法)都需要一个SequenceType参数,因此您可以传递一个数组。 - Antonio
我使用: /* Swift 3.x */ func - <Element: Hashable>(lhs: [Element], rhs: [Element]) -> [Element] { return Array(Set<Element>(lhs).subtracting(Set<Element>(rhs))) } - AmitaiB
4
非常好,它似乎也尊重了原始的顺序 - 这总是可以保证的吗? - Rhythmic Fistman
3
该集合无序且元素唯一。 - Sindre Sorhus
只有在您的元素是“可哈希”的情况下才有用,而对于这种情况,您只需要“可比较”。 - mxcl

9

使用索引数组删除元素:

  1. Array of Strings and indexes

    let animals = ["cats", "dogs", "chimps", "moose", "squarrel", "cow"]
    let indexAnimals = [0, 3, 4]
    let arrayRemainingAnimals = animals
        .enumerated()
        .filter { !indexAnimals.contains($0.offset) }
        .map { $0.element }
    
    print(arrayRemainingAnimals)
    
    //result - ["dogs", "chimps", "cow"]
    
  2. Array of Integers and indexes

    var numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
    let indexesToRemove = [3, 5, 8, 12]
    
    numbers = numbers
        .enumerated()
        .filter { !indexesToRemove.contains($0.offset) }
        .map { $0.element }
    
    print(numbers)
    
    //result - [0, 1, 2, 4, 6, 7, 9, 10, 11]
    
使用另一个数组的元素值来删除元素
  1. Arrays of integers

    let arrayResult = numbers.filter { element in
        return !indexesToRemove.contains(element)
    }
    print(arrayResult)
    
    //result - [0, 1, 2, 4, 6, 7, 9, 10, 11]
    
  2. Arrays of strings

    let arrayLetters = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
    let arrayRemoveLetters = ["a", "e", "g", "h"]
    let arrayRemainingLetters = arrayLetters.filter {
        !arrayRemoveLetters.contains($0)
    }
    
    print(arrayRemainingLetters)
    
    //result - ["b", "c", "d", "f", "i"]
    

4
这是一个带有 @jrc 答案的扩展程序:
extension Array where Element: Equatable {
    func subtracting(_ array: Array<Element>) -> Array<Element> {
        self.filter { !array.contains($0) }
    }
}

不错的方法,但如果你有一百万个条目,这将是n^2。 - Alejandro L.Rocha

3
您可以创建集合,然后使用subtract方法。
let setA = Set(arr1)
let setB = Set(arr2)
setA.subtract(setB)

交集显示共同元素,我想删除共同元素并将其他元素放入另一个数组中。 - Dev Imak
我更新了代码,为此你需要使用减法。 - Adnan Aftab

3

虽然不在范围内,但如果这里有的话,会对我有所帮助。 在OBJECTIVE-C中从数组中移除子数组。

NSPredicate* predicate = [NSPredicate predicateWithFormat:@"not (self IN %@)", subArrayToBeDeleted];
NSArray* finalArray = [initialArray filteredArrayUsingPredicate:predicate];

希望它能够帮助到某些人:)


2
这不是很高效。只需执行以下操作:[[array1 mutableCopy] removeObjectsInArray:array2] - jrc

1

以下是Shai Balassiano的回答的扩展版本:

extension Array where Element: Equatable {
  func subtracting(_ array: [Element]) -> [Element] {
      self.filter { !array.contains($0) }
  }

  mutating func remove(_ array: [Element]) {
      self = self.subtracting(array)
  }
}

0
如果有两个包含重复元素的数组,而你只需要进行简单的减法操作,你可以使用这段代码。这也适用于 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]

0

以下是通过定义自己的PredicateSet来实现的另一种解决方案。

struct PredicateSet<A> {
  let contains: (A) -> Bool
}

let animals = ["Cow", "Bulldog", "Labrador"]
let dogs = ["Bulldog", "Labrador"]

let notDogs = PredicateSet { !dogs.contains($0) }

print(animals.filter(notDogs.contains)) // ["Cow"]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接