Симметричная разница между множеством изменяемых значений создает дубликат - PullRequest
0 голосов
/ 29 июня 2019

Я хочу, чтобы пользователь оценил массив опций по своему вкусу. У меня есть 1 массив, содержащий исходные значения для параметров, 1 массив, содержащий обновленные значения из оригинала. Как я могу получить оставшиеся варианты? Я на Свифте 4.2

Моя идея состоит в том, чтобы преобразовать оба в наборы и использовать симметричную разность.

options array предоставляет исходный выбор
ранжированный массив имеет свойство value ранга пользователя (1,2,3 или 4)
Остальные опции должны содержать фрукты, которые еще не ранжированы

Однако я получаю дубликаты.

Не стесняйтесь предлагать другие способы.

struct Option: Hashable {
    var title: String
    var key: String
    var value: Int
}
var apple = Option(title: "Apple", key: "apple", value: 0)
var grape = Option(title: "Grape", key: "grape", value: 0)
var banana = Option(title: "Banana", key: "banana", value: 0)
var papaya = Option(title: "Papaya", key: "papaya", value: 0)

var options = [apple, grape, banana, papaya]

apple.value = 1
grape.value = 2
var ranked = [apple, grape]

let originalSet: Set<Option> = Set(options)
var rankedSet: Set<Option> = Set(ranked)

let remainingOptions = originalSet.symmetricDifference(rankedSet)

Результат:

{title "Grape", key "grape", value 1}
{title "Apple", key "apple", value 0}
{title "Grape", key "grape", value 2}
{title "Banana", key "banana", value 0}
{title "Apple", key "apple", value 1}
{title "Papaya", key "papaya", value 0}

Требуемый результат:

{title "Banana", key "banana", value 0}
{title "Papaya", key "papaya", value 0}

1 Ответ

1 голос
/ 29 июня 2019

Проблема в том, что вы ожидаете, что два Option будут равны, если они имеют одинаковые title и key, но по умолчанию Swift также проверяет value. Поэтому два Option с разными value считаются разными.

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

Это можно исправить, явно реализовав функции hash(into:) и ==, чтобы игнорировать value при проверке на равенство:

struct Option: Hashable, CustomStringConvertible {
    var title: String
    var key: String
    var value: Int
    var description: String { return "{title: \"\(title)\", key: \"\(key)\", value: \(value)}" }

    func hash(into hasher: inout Hasher) {
        hasher.combine(title)
        hasher.combine(key)
    }

    static func ==(lhs: Option, rhs: Option) -> Bool {
        return lhs.title == rhs.title && lhs.key == rhs.key
    }
}

var apple = Option(title: "Apple", key: "apple", value: 0)
var grape = Option(title: "Grape", key: "grape", value: 0)
var banana = Option(title: "Banana", key: "banana", value: 0)
var papaya = Option(title: "Papaya", key: "papaya", value: 0)

var options = [apple, grape, banana, papaya]

apple.value = 1
grape.value = 2
var ranked = [apple, grape]

let originalSet: Set<Option> = Set(options)
var rankedSet: Set<Option> = Set(ranked)

let remainingOptions = originalSet.symmetricDifference(rankedSet)
print(remainingOptions)
[{title: "Papaya", key: "papaya", value: 0}, {title: "Banana", key: "banana", value: 0}]

Примечание: symmetricDifference принимает последовательность, поэтому нет необходимости преобразовывать ranked в Set, вы можете просто использовать массив:

let remainingOptions = originalSet.symmetricDifference(ranked)

Другой вариант: использовать фильтр

Вместо использования Set s и symmetricDifference вы можете использовать map, чтобы получить массив keys из массива ranked, а затем использовать filter в массиве options, чтобы получить remaining параметры, которые не соответствуют этим keys:

let rankedKeys = ranked.map { $0.key }
let remaining = options.filter { !rankedKeys.contains($0.key) }

Для этого не требуется изменять структуру Option по сравнению с исходным определением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...