我有一个对象数组,我想根据属性比较对象,以了解属性是否全部相同。现在,我遍历所有对象,将所有属性值放置在单独的数组中,然后使用filterArr.allSatisfy { $0 == filterArr.last }
来确定属性是否相同。
此方法有效,但我知道必须比我正在做的事情更优雅。
我实际上是在寻找答案,但是我遇到的每件事都是比较2个不同数组(而不是1个)的元素。
class IceCream {
var flavor: String?
var price: Double?
}
let iceCream1 = IceCream()
iceCream1.flavor = "vanilla"
iceCream1.price = 1.5
let iceCream2 = IceCream()
iceCream2.flavor = "chocolate"
iceCream2.price = 2.0
let iceCream3 = IceCream()
iceCream3.flavor = "vanilla"
iceCream3.price = 1.5
let iceCream4 = IceCream()
iceCream4.flavor = "strawberry"
iceCream4.price = 2.5
let iceCreams = [iceCream1, iceCream2, iceCream3, iceCream4]
var filterArr = [String]()
for iceCream in iceCreams {
filterArr.append(iceCream.flavor ?? "")
}
let areItemsEqual = filterArr.allSatisfy { $0 == filterArr.last }
print(areItemsEqual) // prints false
答案 0 :(得分:1)
您可以避免必须初始化,然后再使用结构在单独的行上分配属性。
struct IceCream {
let flavor: String?
let price: Double?
}
let iceCreams: [IceCream] = [
IceCream(flavor: "vanilla", price: 1.5),
IceCream(flavor: "chocolate", price: 2.0),
IceCream(flavor: "vanilla", price: 1.5),
IceCream(flavor: "strawberry", price: 2.5)
]
使用@Alexander和@matt提供的仿制药,我们有一个不错的扩展名。
extension Collection {
func allEqual<T: Equatable>(by key: KeyPath<Element, T>) -> Bool {
return allSatisfy { first?[keyPath:key] == $0[keyPath:key] }
}
}
print(iceCreams.allEqual(by: \.flavor))
或者,您可以指定IceCream
在口味上彼此相等。
extension IceCream: Equatable {
static func == (lhs: IceCream, rhs: IceCream) -> Bool {
return lhs.flavor == rhs.flavor
}
}
extension Collection where Element: Equatable {
func allEqual() -> Bool {
return allSatisfy { first == $0 }
}
}
print(iceCreams.allEqual())
答案 1 :(得分:1)
这是一种非常快捷的方法。我在Collection
上定义了一个扩展,用于根据给定的谓词检查集合项之间的相等性:
extension Collection {
func allEqual<T: Equatable>(by deriveKey: (Element) -> T) -> Bool {
guard let firstElement = self.first else {
return true // empty lists are all-equal
}
let sampleKey = deriveKey(firstElement)
return self.dropFirst().allSatisfy{ deriveKey($0) == sampleKey }
}
}
struct IceCream {
let flavor: String
let price: Double
}
let iceCreams = [
IceCream(flavor: "vanilla", price: 1.5),
IceCream(flavor: "chocolate", price: 2.0),
IceCream(flavor: "vanilla", price: 1.5),
IceCream(flavor: "strawberry", price: 2.5)
]
let allItemsEqualByFlavour = iceCreams.allEqual(by: { $0.flavor})
print(allItemsEqualByFlavour) // false
let vanillaOnlyIceCreams = iceCreams.filter{ $0.flavor == "vanilla" }
print(vanillaOnlyIceCreams.allEqual(by: { $0.flavor})) // true
答案 2 :(得分:1)
这是确保您的冰淇淋在任意轴上都是相同的一种优雅方法,即您以后可以注入的风味或价格或任何其他适量特性:
extension Array {
func allSameForProperty<T:Equatable> (_ p:KeyPath<Element,T>) -> Bool {
return self.isEmpty || self.allSatisfy{
self.first![keyPath:p] == $0[keyPath:p]
}
}
}
让我们测试一下。首先,一些初始条件:
struct Icecream {
let flavor : String
let price : Double
}
let arr = [
Icecream(flavor: "vanilla", price: 1.5),
Icecream(flavor: "vanilla", price: 1.75)
]
现在是实际测试:
arr.allSameForProperty(\Icecream.flavor) // true
arr.allSameForProperty(\Icecream.price) // false