【问题标题】:How can I get all unique elements from a collection in Swift如何从 Swift 中的集合中获取所有唯一元素
【发布时间】:2017-09-22 22:06:23
【问题描述】:

如果我得到这个数组:

[0, 0, 1, 1, 1, 2, 3, 4, 5, 5]

如何获得:

[2, 3, 4]

This answer 将保存副本的值,但我也想删除该值。

【问题讨论】:

标签: swift


【解决方案1】:

请注意,您需要导入 Foundation 才能使用 NSCountedSet。如果您需要一个纯 Swift 解决方案来查找集合的唯一元素,您可以将其扩展为限制元素到 Equatable 协议并检查是否可以 not 再次找到元素索引检查是否 index(of: element) == nil 使用 index(after:) 元素索引作为集合子序列的 startIndex:

编辑/更新:Swift 4.2.1

请注意,扩展 RangeReplacebleCollection 它将涵盖 StringProtocol 类型 StringSubstring 以及:

将元素限制为Equatable

Xcode 11 • Swift 5.1

extension RangeReplaceableCollection where Element: Equatable {
    var uniqueElements: Self {
        filter { self[index(after: firstIndex(of: $0)!)...].firstIndex(of: $0) == nil }
    }
    mutating func removeAllNonUniqueElements() { self = uniqueElements }
}

如果您不需要保持集合的原始顺序,您可以利用新的 Dictionary 初始化程序,但这需要将元素限制为 Hashable

init<S>(grouping values: S, by keyForValue: (S.Element) throws -> Dictionary<Key, Value>.Key) rethrows where Value == [S.Element], S : Sequence

并保留值等于 1 的键

extension RangeReplaceableCollection where Element: Hashable {
    var uniqueElementsSet: Set<Element> {
       Set(Dictionary(grouping: self, by: { $0 }).compactMap{ $1.count == 1 ? $0 : nil })
    }
}

游乐场测试

let numbers = [0, 0, 1, 1, 1, 2, 3, 4, 5, 5]
numbers.uniqueElements    // [4, 2, 3]

如果您需要保持集合的顺序,您可以获取此answer 中所示的元素频率并过滤唯一元素:

extension Sequence where Element: Hashable {
    var frequency: [Element: Int] { reduce(into: [:]) { $0[$1, default: 0] += 1 } }
}

extension RangeReplaceableCollection where Element: Hashable {
    var uniqueElements:  Self { filter { frequency[$0] == 1 } }
    mutating func removeAllNonUniqueElements() { self = uniqueElements }
}

游乐场测试

let numbers = [0, 0, 1, 1, 1, 2, 3, 4, 5, 5]
numbers.uniqueElements   // [2, 3, 4]

var string = "0011123455"
string.uniqueElements       // "234"
string.uniqueElementsSet    // {"4", "3", "2"}
print(string)  // "0011123455\n"

 // mutating the string
string.removeAllNonUniqueElements()
print(string)  // 234

【讨论】:

  • 谢谢我会使用那个扩展!
【解决方案2】:

如果您只想过滤出现 1 次的数字,您可以使用旧的 NSCountedSet

let nums = [0, 0, 1, 1, 1, 2, 3, 4, 5, 5]
let countedSet = NSCountedSet(array: nums)
let uniques = nums.filter { countedSet.count(for: $0) == 1 }

print(uniques) // [2, 3, 4]

【讨论】:

    猜你喜欢
    • 2018-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-17
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 2011-07-19
    相关资源
    最近更新 更多