Объедините 2 колоды с разными номерами

#swift #algorithm

Вопрос:

Мне нужно объединить набор цепей, и я как бы застрял, давайте приведем в качестве примера колоду. Допустим, у меня есть 2 набора чисел:

 deck1 = [1, 2]
deck2 = [1, 15, 2]
 

Я хочу найти в нем все одинаковые и разные # и сохранить их в новой колоде, ожидаемый результат таков:

 [1, 15, 2]
 

где я забочусь о предыдущем порядке массива, например: [1, 2], но не о новом, поэтому новый должен выглядеть так: [1, 2, 15] или [1, 15, 2] только в этих двух случаях.

Для этого я создал двойной цикл:

 var newDeck = []

for deck1 in deck1 {
    for deck2 in deck2 {
        if(deck1 == deck2) {
            newDeck.append(deck1)
        } else {
            
        }
    }
}
 

Я знаю, как сделать часть==, но я не уверен в остальном. Решение, которое я придумал, состояло в добавлении еще одного цикла (lol) в else, а затем я понял, что мне нужна помощь. Как я могу решить эту маленькую головоломку?

Спасибо

Правка: Еще одна идея, о которой я сейчас думал, — это добавление значений первого цикла в диктант, и если его там нет, добавьте его, но не снизится ли при этом производительность?

Комментарии:

1. Вам следует изучить тип набора коллекций, это может быть действительно полезно для такого рода проблем.

2. хорошо смотрю @JoakimDanielson

3. @JoakimDanielson проблема наборов для того, что я вижу, заключается в том, что при их хранении у них нет определенного порядка. Мне нужно, чтобы товары были заказаны

4. Вам не нужно хранить значения в наборе , вы можете просто использовать их в качестве промежуточного решения для поиска одинаковых и разных значений

5. Ваш образец с его «ожидаемым результатом» неясен. Вы можете захотеть иметь другой вход и показать ожидаемый результат, потому что в настоящее время это так deck2 , но почему?

Ответ №1:

Возможный способ — получить разницу с помощью CollectionDifference и применять только вставки

 let deck1 = [1, 2]
let deck2 = [1, 15, 2]

var result = deck2

let difference = deck1.difference(from: deck2)
for change in difference {
    if case let .insert(offset, newElement, _) = change {
        result.insert(newElement, at: offset)
    }
}

print(result)
 

Комментарии:

1. Хороший подход. Единственным недостатком является то, что CollectionDifference iOS 13 (в случае, если разработчику вроде меня все еще нужна iOS 12 )

2. @Ларме повезло, что я использую iOS 15, хахаха

Ответ №2:

Если бы я понял логику, которую вы не совсем объясняете…

Я думаю, логика такова:
мы проверяем элемент с индексом 0 обоих массивов, мы вставляем их в результат, если его еще нет.
Мы проверяем элемент по индексу 1 обоих массивов, вставляем их в результат, если его еще нет.
Мы проверяем элемент по индексу 2 обоих массивов, вставляем их в результат, если его еще нет.
И так далее…

Но, как сказано в комментарии, я не уверен, что вы не объясняете это полностью, и ваши образцы могут быть неверно истолкованы, поскольку они не охватывают все случаи (и не объясняется, почему там должно быть какое-то значение или нет).

Итак, оба метода должны сработать. Я сохранил Set версию для иллюстрации, так как у них нет дубликатов, и тогда поиск должен быть быстрее…

Чтобы избежать выхода за пределы, я проверил меньший массив и сохранил последние значения rest .

 func merge(deck1: [Int], deck2: [Int]) {
    var valuesAlreadySaved: Set<Int> = Set()

    var result: [Int] = []
    var rest: [Int] = []
    let min = min(deck1.count, deck2.count)
    if deck1.count > min {
        rest.append(contentsOf: deck1.dropFirst(min))
    } else {
        rest.append(contentsOf: deck2.dropFirst(min))
    }
    print("Rest: (rest)")
    for index in 0..<min {
        let value1 = deck1[index]
        let value2 = deck2[index]
        if !valuesAlreadySaved.contains(value1) {
            result.append(value1)
            valuesAlreadySaved.insert(value1)
        }
        if !valuesAlreadySaved.contains(value2) {
            result.append(value2)
            valuesAlreadySaved.insert(value2)
        }
    }

    for aValue in rest {
        if !valuesAlreadySaved.contains(aValue) {
            result.append(aValue)
            valuesAlreadySaved.insert(aValue)
        }
    }

    print("Input: (deck1) - (deck2)")
    print("Result: (result)")
}

merge(deck1: [1, 2], deck2: [1, 15, 2])
merge(deck1: [1, 3, 2], deck2: [1, 15, 2])

func mergeWithoutSet(deck1: [Int], deck2: [Int]) {

    var result: [Int] = []
    var rest: [Int] = []
    let min = min(deck1.count, deck2.count)
    if deck1.count > min {
        rest.append(contentsOf: deck1.dropFirst(min))
    } else {
        rest.append(contentsOf: deck2.dropFirst(min))
    }
    print("Rest2: (rest)")
    for index in 0..<min {
        let value1 = deck1[index]
        if !result.contains(value1) {
            result.append(value1)
        }
        let value2 = deck2[index]
        if !result.contains(value2) {
            result.append(value2)
        }
    }

    for aValue in rest {
        if !result.contains(aValue) {
            result.append(aValue)
        }
    }

    print("Input2: (deck1) - (deck2)")
    print("Result2: (result)")
}

mergeWithoutSet(deck1: [1, 2], deck2: [1, 15, 2])
mergeWithoutSet(deck1: [1, 3, 2], deck2: [1, 15, 2])

 

И это может быть факторизовано с помощью:

 func mergeWithoutSet2(deck1: [Int], deck2: [Int]) {

    var result: [Int] = []
    let min = min(deck1.count, deck2.count)
    let rest = deck1.count > min ? deck1.dropFirst(min) : deck2.dropFirst(min)
    print("Rest3: (rest)")

    func appendIfNeeded(_ value: Int, to array: inout [Int]) {
        guard !array.contains(value) else { return }
        array.append(value)
    }
    for index in 0..<min {
        appendIfNeeded(deck1[index], to: amp;result)
        appendIfNeeded(deck2[index], to: amp;result)
    }

    for aValue in rest {
        appendIfNeeded(aValue, to: amp;result)
    }

    print("Input3: (deck1) - (deck2)")
    print("Result3: (result)")
}
 

Ответ №3:

Первый метод состоит в том, чтобы суммировать два массива, а затем использовать contains функцию для проверки нового массива на наличие значений и устранения избыточности.

 let deck1 = [1, 2]
let deck2 = [1, 15, 2]

var deck = deck1   deck2

var newDeck = [Int]()
for i in deck {
    if newDeck.contains(i) == false {
        newDeck.append(i)
    }
}
print(newDeck)
 

Второй способ — использовать Set . Объедините два массива и преобразуйте их в наборы. Набор не допускает избыточности, поэтому повторяющееся значение автоматически удаляется. После этого измените его обратно на прежнее расположение.

 let deck1 = [1, 2]
let deck2 = [1, 15, 2]

var deck = deck1   deck2

let newDeck: Set = Set(deck)
Array(newDeck)