#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)