答案 0 :(得分:5)
请注意,您需要导入Foundation才能使用NSCountedSet。如果您需要一个纯Swift解决方案来查找集合的唯一元素,您可以扩展它将元素约束到Equatable协议并检查是否可以不再次查找元素索引,检查是否为index(of: element)== nil使用索引(后:)将元素索引作为集合子序列的startIndex:
修改/更新: Swift 4.2.1
请注意,扩展RangeReplacebleCollection将涵盖StringProtocol类型String
和Substring
:
将元素约束到Equatable
extension RangeReplaceableCollection where Element: Equatable {
var uniqueElements: Self {
return filter {
if let index = self.index(of: $0),
self[self.index(after: index)...].index(of: $0) == nil {
return true
}
return false
}
}
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> {
return 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] {
return reduce(into: [:]) { $0[$1, default: 0] += 1 }
}
}
extension RangeReplaceableCollection where Element: Hashable {
var uniqueElements: Self {
return 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
答案 1 :(得分:3)
如果您只想过滤一次出现的数字,可以使用旧的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]