如何从Swift中的集合中获取所有独特元素

时间:2017-09-22 22:06:23

标签: swift

如果我有这个阵列:

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

我怎样才能得到:

[2, 3, 4]

This answer会保留重复的值,但我也想删除该值。

2 个答案:

答案 0 :(得分:5)

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

修改/更新: Swift 4.2.1

请注意,扩展RangeReplacebleCollection将涵盖StringProtocol类型StringSubstring

将元素约束到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]