首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按属性在一个数组中迅速使用iOS -Compare元素

按属性在一个数组中迅速使用iOS -Compare元素
EN

Stack Overflow用户
提问于 2018-12-29 23:48:14
回答 3查看 4.5K关注 0票数 2

我有一个对象数组,我想根据属性比较这些对象,以确定这些属性是否都是相同的。现在,我循环遍历所有对象,将属性的所有值放在一个单独的数组中,然后使用filterArr.allSatisfy { $0 == filterArr.last }来确定属性是否都相同。

这个方法有效,但我知道必须有一个比我所做的更优雅的方法。

我实际上是在寻找答案,但我遇到的每一件事都是比较两个不同数组的元素,而不是一个。

代码语言:javascript
复制
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
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-12-29 23:56:16

您可以避免必须初始化属性,然后使用结构在单独的行上分配属性。

代码语言:javascript
复制
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提供的泛型糖,我们有一个漂亮的扩展。

代码语言:javascript
复制
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在风味上是相等的。

代码语言:javascript
复制
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())
票数 2
EN

Stack Overflow用户

发布于 2018-12-30 00:03:45

这是一种非常快捷的方法。我在Collection上定义了一个扩展,根据给定的谓词检查集合的项之间是否相等:

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2018-12-30 00:08:44

这里有一种优雅的方法,可以确保您的冰淇淋在任意轴上都是相同的,即味道或价格,或者以后可能注入的任何其他等价物:

代码语言:javascript
复制
extension Array {
    func allSameForProperty<T:Equatable> (_ p:KeyPath<Element,T>) -> Bool {
        return self.isEmpty || self.allSatisfy{
            self.first![keyPath:p] == $0[keyPath:p]
        }
    }
}

我们来测试一下。第一,一些初始条件:

代码语言:javascript
复制
struct Icecream {
    let flavor : String
    let price : Double
}
let arr = [
    Icecream(flavor: "vanilla", price: 1.5),
    Icecream(flavor: "vanilla", price: 1.75)
]

现在实际的测试是:

代码语言:javascript
复制
arr.allSameForProperty(\Icecream.flavor) // true
arr.allSameForProperty(\Icecream.price) // false
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53974239

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档