На основе https://www.swiftbysundell.com/posts/the-power-of-key-paths-in-swift, мы можем объявить более мощный инструмент, который может фильтровать уникальность по любому ключевому пути. Благодаря комментариям Александра к различным ответам относительно сложности, приведенные ниже решения должны быть близки к оптимальным.
Не мутирующее решение
Мы расширяем его функцией, которая может фильтровать уникальность по любому keyPath:
extension RangeReplaceableCollection {
/// Returns a collection containing, in order, the first instances of
/// elements of the sequence that compare equally for the keyPath.
func unique<T: Hashable>(for keyPath: KeyPath<Element, T>) -> Self {
var unique = Set<T>()
return filter { unique.insert($0[keyPath: keyPath]).inserted }
}
}
Примечание: в случае, если ваш объект не соответствует RangeReplaceableCollection, но соответствует Sequence, у вас может быть это дополнительное расширение, но возвращаемый тип всегда будет массивом:
extension Sequence {
/// Returns an array containing, in order, the first instances of
/// elements of the sequence that compare equally for the keyPath.
func unique<T: Hashable>(for keyPath: KeyPath<Element, T>) -> [Element] {
var unique = Set<T>()
return filter { unique.insert($0[keyPath: keyPath]).inserted }
}
}
использование
Если мы хотим уникальности для самих элементов, как в вопросе, мы используем keyPath \.self
:
let a = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
let b = a.unique(for: \.self)
/* b is [1, 4, 2, 6, 24, 15, 60] */
Если мы хотим уникальности для чего-то еще (например, для id
коллекции объектов), мы используем keyPath по нашему выбору:
let a = [CGPoint(x: 1, y: 1), CGPoint(x: 2, y: 1), CGPoint(x: 1, y: 2)]
let b = a.unique(for: \.y)
/* b is [{x 1 y 1}, {x 1 y 2}] */
Мутирующее решение
Мы расширяем мутирующую функцию, которая может фильтровать уникальность по любому keyPath:
extension RangeReplaceableCollection {
/// Keeps only, in order, the first instances of
/// elements of the collection that compare equally for the keyPath.
mutating func uniqueInPlace<T: Hashable>(for keyPath: KeyPath<Element, T>) {
var unique = Set<T>()
removeAll { !unique.insert($0[keyPath: keyPath]).inserted }
}
}
использование
Если мы хотим уникальности для самих элементов, как в вопросе, мы используем keyPath \.self
:
var a = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
a.uniqueInPlace(for: \.self)
/* a is [1, 4, 2, 6, 24, 15, 60] */
Если нам нужна уникальность для чего-то еще (например, для id
коллекции объектов), мы используем keyPath по нашему выбору:
var a = [CGPoint(x: 1, y: 1), CGPoint(x: 2, y: 1), CGPoint(x: 1, y: 2)]
a.uniqueInPlace(for: \.y)
/* a is [{x 1 y 1}, {x 1 y 2}] */
person
Cœur
schedule
15.04.2019
NSSet
, NSSet представляет собой неупорядоченный набор объектов, если необходимо сохранить порядок NSOrderedSet. - person Andrea   schedule 09.09.2014$.uniq(array)
github.com/ankurp/Dollar#uniq---uniq - person Andrew   schedule 06.12.2016Set
от Swift? Вы сможете предоставить список неупорядоченных и уникальных элементов. - person TibiaZ   schedule 11.03.2019