You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从类对象数组中提取指定属性的唯一值?

从对象数组的指定属性提取唯一值

好问题!确实,直接用Array(Set(myArray))这套玩法只适用于值类型的数组——比如你提到的[1,2,2,3]这种,因为每个元素都是独立的值。但对于Alert这种引用类型的对象数组,每个实例都是独一无二的,Set根本识别不出它们的属性重复,所以这套方法就失效了。下面给你几个实用的解决方案:

方法1:先抽属性再去重(最直观)

思路很简单:先把数组里每个Alert对象的目标属性提取出来,变成一个值类型数组,再用Set去重,最后转回数组就行。

因为你的Alert属性都是可选类型(比如category: String?),所以推荐用compactMap过滤掉nil值,避免出现[String?]这种包含空值的数组:

// 假设你有一个Alert数组
let alerts: [Alert] = // 你的数据源
// 提取category的唯一非空值
let uniqueCategories = Array(Set(alerts.compactMap { $0.category }))

如果你不想过滤nil,只是要保留可选值的唯一组合,把compactMap换成map就行:

let uniqueCategoryIds = Array(Set(alerts.map { $0.category_id }))

方法2:保持顺序的去重方案

上面的Set方法会打乱原数组中属性出现的顺序,如果你需要保留第一次出现的顺序,可以用reduce手动构建唯一数组:

let uniqueOrderedCategories = alerts.compactMap { $0.category }.reduce(into: [String]()) { result, category in
    if !result.contains(category) {
        result.append(category)
    }
}

这个方法会严格按照属性在原数组中首次出现的顺序排列,适合需要保持时序的场景。

方法3:写个扩展让代码复用性拉满

如果以后经常要从不同对象数组提取属性的唯一值,不如给Array写个扩展,用KeyPath来指定属性,这样调用起来超方便:

extension Array {
    // 无序去重(过滤nil)
    func uniqueValues<T: Hashable>(for keyPath: KeyPath<Element, T?>) -> [T] {
        return Array(Set(compactMap { $0[keyPath: keyPath] }))
    }
    
    // 有序去重(过滤nil)
    func uniqueValuesOrdered<T: Equatable>(for keyPath: KeyPath<Element, T?>) -> [T] {
        return compactMap { $0[keyPath: keyPath] }.reduce(into: [T]()) { result, value in
            if !result.contains(value) {
                result.append(value)
            }
        }
    }
}

使用的时候一行代码搞定:

let uniqueCategories = alerts.uniqueValues(for: \.category)
let uniqueOrderedIds = alerts.uniqueValuesOrdered(for: \.category_id)

小提示

  • 如果你的Alert属性改成非可选类型(比如var category: String),可以把扩展里的T?改成T,compactMap换成map就行。
  • 只有符合Hashable协议的类型才能用Set去重,Swift自带的String、Int、Bool这些基本类型都没问题,自定义类型要支持的话记得实现Hashable协议。

内容的提问来源于stack exchange,提问作者CodeLikeBeaker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:14:51