요즘 Swift에서는 간단히 입력 Set( yourArray )
하여 배열을 고유하게 만듭니다. (또는 필요한 경우 주문 세트.)
그 전에는 어떻게 되었습니까?
다음과 같은 배열이있을 수 있습니다.
[1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
또는 실제로 같은 유형의 데이터 부분 시퀀스. 내가하고 싶은 것은 각각의 동일한 요소 중 하나만 있는지 확인하는 것입니다. 예를 들어 위의 배열은 다음과 같습니다.
[1, 4, 2, 6, 24, 15, 60]
2, 6 및 15의 복제본이 제거되어 동일한 각 요소 중 하나만 있음을 확인했습니다. Swift가이를 쉽게 수행 할 수있는 방법을 제공합니까, 아니면 직접해야합니까?
답변
예를 들어 다음과 같이 직접 롤백 할 수 있습니다 ( Swift 1.2에서 Set로 업데이트 )
func uniq<S : SequenceType, T : Hashable where S.Generator.Element == T>(source: S) -> [T] {
var buffer = [T]()
var added = Set<T>()
for elem in source {
if !added.contains(elem) {
buffer.append(elem)
added.insert(elem)
}
}
return buffer
}
let vals = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
let uniqueVals = uniq(vals) // [1, 4, 2, 6, 24, 15, 60]
스위프트 3 버전 :
func uniq<S : Sequence, T : Hashable>(source: S) -> [T] where S.Iterator.Element == T {
var buffer = [T]()
var added = Set<T>()
for elem in source {
if !added.contains(elem) {
buffer.append(elem)
added.insert(elem)
}
}
return buffer
}
그리고 다음의 확장으로 Array
:
extension Array where Element: Hashable {
var uniques: Array {
var buffer = Array()
var added = Set<Element>()
for elem in self {
if !added.contains(elem) {
buffer.append(elem)
added.insert(elem)
}
}
return buffer
}
}
답변
집합으로 변환하고 다시 배열로 쉽게 다시 변환 할 수 있습니다.
let unique = Array(Set(originals))
어레이의 원래 순서를 유지한다고 보장 할 수는 없습니다.
답변
여기에 많은 답변이 있지만 Swift 2 이상에 적합한이 간단한 확장을 놓쳤습니다.
extension Array where Element:Equatable {
func removeDuplicates() -> [Element] {
var result = [Element]()
for value in self {
if result.contains(value) == false {
result.append(value)
}
}
return result
}
}
매우 간단합니다. 다음과 같이 호출 할 수 있습니다.
let arrayOfInts = [2, 2, 4, 4]
print(arrayOfInts.removeDuplicates()) // Prints: [2, 4]
속성을 기반으로 필터링
속성을 기준으로 배열을 필터링하려면이 방법을 사용할 수 있습니다.
extension Array {
func filterDuplicates(@noescape includeElement: (lhs:Element, rhs:Element) -> Bool) -> [Element]{
var results = [Element]()
forEach { (element) in
let existingElements = results.filter {
return includeElement(lhs: element, rhs: $0)
}
if existingElements.count == 0 {
results.append(element)
}
}
return results
}
}
다음과 같이 전화를 걸 수 있습니다.
let filteredElements = myElements.filterDuplicates { $0.PropertyOne == $1.PropertyOne && $0.PropertyTwo == $1.PropertyTwo }
답변
스위프트 3.0
let uniqueUnordered = Array(Set(array))
let uniqueOrdered = Array(NSOrderedSet(array: array))
답변
코드에 두 확장을 모두 넣으면 Hashable
가능 하면 더 빠른 버전이 Equatable
사용되며 대체 버전으로 사용됩니다.
public extension Sequence where Element: Hashable {
var firstUniqueElements: [Element] {
var set: Set<Element> = []
return filter { set.insert($0).inserted }
}
}
public extension Sequence where Element: Equatable {
var firstUniqueElements: [Element] {
reduce(into: []) { uniqueElements, element in
if !uniqueElements.contains(element) {
uniqueElements.append(element)
}
}
}
}
순서가 중요하지 않은 경우 항상 이 Set initializer 만 사용할 수 있습니다 .
답변
Swift 4 이상 편집 / 업데이트
또한 RangeReplaceableCollection
프로토콜을 확장 하여 StringProtocol
유형 에도 사용할 수 있습니다.
extension RangeReplaceableCollection where Element: Hashable {
var orderedSet: Self {
var set = Set<Element>()
return filter { set.insert($0).inserted }
}
mutating func removeDuplicates() {
var set = Set<Element>()
removeAll { !set.insert($0).inserted }
}
}
let integers = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
let integersOrderedSet = integers.orderedSet // [1, 4, 2, 6, 24, 15, 60]
"abcdefabcghi".orderedSet // "abcdefghi"
"abcdefabcghi".dropFirst(3).orderedSet // "defabcghi"
돌연변이 방법 :
var string = "abcdefabcghi"
string.removeDuplicates()
string // "abcdefghi"
var substring = "abcdefabcdefghi".dropFirst(3) // "defabcdefghi"
substring.removeDuplicates()
substring // "defabcghi"
들어 스위프트 3 클릭 여기
답변
스위프트 4
public extension Array where Element: Hashable {
func uniqued() -> [Element] {
var seen = Set<Element>()
return filter{ seen.insert($0).inserted }
}
}
모든 시도 insert
는 또한 튜플을 반환합니다 : (inserted: Bool, memberAfterInsert: Set.Element)
. 설명서를 참조하십시오 .
반환 된 값을 사용하면 루핑이나 다른 작업을 피할 수 있습니다.