我有一个对象数组,我想根据属性比较这些对象,以确定这些属性是否都是相同的。现在,我循环遍历所有对象,将属性的所有值放在一个单独的数组中,然后使用filterArr.allSatisfy { $0 == filterArr.last }来确定属性是否都相同。
这个方法有效,但我知道必须有一个比我所做的更优雅的方法。
我实际上是在寻找答案,但我遇到的每一件事都是比较两个不同数组的元素,而不是一个。
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发布于 2018-12-29 23:56:16
您可以避免必须初始化属性,然后使用结构在单独的行上分配属性。
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())发布于 2018-12-30 00:03:45
这是一种非常快捷的方法。我在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发布于 2018-12-30 00:08:44
这里有一种优雅的方法,可以确保您的冰淇淋在任意轴上都是相同的,即味道或价格,或者以后可能注入的任何其他等价物:
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) // falsehttps://stackoverflow.com/questions/53974239
复制相似问题