我希望用户根据自己的喜好对一系列选项进行排序。 我有1个数组保存选项的原始值,1个数组保存原始值的更新值。 我如何获得剩余的选择权? 我正在使用Swift 4.2
我的想法是将两者都转换为集合并使用对称差。
选项数组提供了原始选择
排名数组具有用户等级(1、2、3或4)的value属性。
remainingOptions 应该包含尚未排名的水果
但是,我得到重复了。
随时提出其他建议。
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}
答案 0 :(得分:1)
问题在于,如果两个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
,您可以使用数组:< / p>
let remainingOptions = originalSet.symmetricDifference(ranked)
另一个选项:使用过滤器
您可以使用Set
从symmetricDifference
数组中获取map
的数组,然后再使用{而不是使用keys
和ranked
filter
数组上的{1}},以获取与options
不匹配的remaining
选项:
keys
这不需要您从原始定义中更改let rankedKeys = ranked.map { $0.key }
let remaining = options.filter { !rankedKeys.contains($0.key) }
结构。