2015-04-13 2 views

ответ

13

Как это:

var arrayA = ["Mike", "James", "Stacey", "Steve"] 
var arrayB = ["Steve", "Gemma", "James", "Lucy"] 
for word in arrayB { 
    if let ix = find(arrayA, word) { 
     arrayA.removeAtIndex(ix) 
    } 
} 
// now arrayA is ["Mike", "Stacey"] 
+1

Это оказалось правильным ответом, спасибо. –

+7

Это решение хорошо подходит для небольших массивов, но его необходимо учитывать, что его сложность O (n^2). Для больших массивов я бы рассмотрел преобразование 'arrayA' в набор и использование его для' find' - это должно уменьшить сложность до O (2n) – Antonio

24

Самый простой способ заключается в использовании нового Set контейнера (добавленный в Swift 1.2/Xcode 6.3):

var setA = Set(arrayA) 
var setB = Set(arrayB) 

// Return a set with all values contained in both A and B 
let intersection = setA.intersect(setB) 

// Return a set with all values in A which are not contained in B 
let diff = setA.subtract(setB) 

Если вы хотите переназначить образовавшееся установлен arrayA, просто создать новый экземпляр, используя копию конструктор и присвоить его arrayA:

arrayA = Array(intersection) 

недостатком является то, что вы должны создать 2 новых наборов данных. Обратите внимание, что intersect не мутирует экземпляр, в который он вызывается, он просто возвращает новый набор.

Есть аналогичные методы для сложения, вычитания и т.д., вы можете посмотреть на них

+0

Извините, что я никогда не использовал Установить раньше. Я только что бросил его на детскую площадку, и он говорит: «Использовать неразрешенный идентификатор« Установить ». Можете ли вы подробнее рассказать? –

+0

Забыл упомянуть, что он доступен в Swift 1.2 - я полагаю, вы не используете Xcode 6.3 – Antonio

+0

Ahh Хорошо, вы предполагаете, что я сейчас обновись и отдам его. Спасибо за вашу помощь. –

9

Я согласен с ответом Антонио, однако для небольших вычетов массива вы можете также использовать замыкание фильтра, как это:

let res = arrayA.filter { !contains(arrayB, $0) } 
+0

Это хорошо, потому что он сохраняет порядок – Alexander

4

Это также может быть реализован как минус FUNC:

func -<T:RangeReplaceableCollectionType where T.Generator.Element:Equatable>(lhs:T, rhs:T) -> T { 

    var lhs = lhs 
    for element in rhs { 
     if let index = lhs.indexOf(element) { lhs.removeAtIndex(index) } 
    } 

    return lhs 
} 

Теперь вы можете использовать

arrayA - arrayB 
25

@ ответ FRANCESCO-vadicamo в Swift +

arrayA = arrayA.filter { !arrayB.contains($0) } 
+0

Должен повернуть 'arrayB' в' Set «первый. – BallpointBen

+0

@BallpointBen почему? это не то, что ОП спросил –

+0

@BallpointBen Я добавил демонстрационную ссылку на ответ: как вы можете видеть, он работает так, как ожидалось. –

9

решений матовых и Freytag х 2/3/4 являются только те, на которые приходится дублей и должен получать больше + 1, чем другие ответы.

Вот обновленная версия ответа мата для Swift 3.0:

var arrayA = ["Mike", "James", "Stacey", "Steve"] 
var arrayB = ["Steve", "Gemma", "James", "Lucy"] 
for word in arrayB { 
    if let ix = arrayA.index(of: word) { 
     arrayA.remove(at: ix) 
    } 
} 
2

Используя Array → Set → Array метод, упомянутый Антонио, и с удобством оператора, так как Freytag указал, я был очень доволен, используя это:

// Swift 3.x 
func - <Element: Hashable>(lhs: [Element], rhs: [Element]) -> [Element] 
{ 
    return Array(Set<Element>(lhs).subtracting(Set<Element>(rhs))) 
} 
1

Здесь находятся одни и те же операции с массивом целых чисел Swift 3

var array1 = [1, 2, 3, 4, 5, 6] 

var array2 = [1,5] 

var arrayResult = array1.enumerated() 
    .filter { !array2.contains($0.0 + 1) } 
    .map { $0.1 } 

print(arrayResult) 

[2, 3, 4, 6]


Еще способы достижения такого же результата:

1. Использование фильтра

let arrayResult = array1.filter { element in 
    return !array2.contains(element) 
} 

2. Использование сортировки

array2.sorted(by: >).forEach { if $0 < self.array1.count { self.array1.remove(at: $0) } } 
Смежные вопросы