2017-02-03 4 views

ответ

7

Вы можете использовать функцию массива contains(_:), чтобы проверить, является ли элемент уже частью массива, но это довольно медленно, и для больших массивов он не будет работать хорошо. Лучше скопировать записи в Set и использовать операции Set для поиска и удаления дубликатов. Наборы оптимизированы для быстрого тестирования набора для набора, поэтому if aSet.contains(item) намного быстрее, чем if anArray.contains(item).

Если вы не заботитесь о сохранении порядка своих товаров, вы можете просто скопировать массив в набор, а затем вернуться к массиву. Однако это означает, что элементы в результирующем массиве будут в другом порядке.

Функция для удаления дубликатов из массива строк, сохраняя при этом порядок, может выглядеть следующим образом:

func uniqueElementsFrom(array: [String]) -> [String] { 
    //Create an empty Set to track unique items 
    var set = Set<String>() 
    let result = array.filter { 
    guard !set.contains($0) else { 
     //If the set already contains this object, return false 
     //so we skip it 
     return false 
    } 
    //Add this item to the set since it will now be in the array 
    set.insert($0) 
    //Return true so that filtered array will contain this item. 
    return true 
    } 
    return result 
} 

Если вы вызываете его с кодом, как это:

let arrayOfStrings = ["a", "b", "a", "c", "a", "d"] 
let uniqueStrings = uniqueElementsFrom(array:arrayOfStrings) 
print("Unique elements from \(arrayOfStrings) = \n” + 
    “\(uniqueStrings)") 

Выход будет

Уникальные элементы из [ "а", "б", "A", "C", "A", "D"] =

[ «а», "б", "в", "г"]

Тем не менее, эта функция работает только с массивами строк. Было бы хорошо, если бы мы могли написать функцию, которая могла бы удалить дубликаты из любого типа массива.

Это работа для дженериков. Однако есть уловка. Наборы могут содержать только объекты, которые соответствуют протоколу Hashable, так как Sets использует хэши, чтобы быстрее выполнять тестирование для установления членства.

Мы можем переписать функцию uniqueElementsFrom(array:), чтобы взять любой массив, который соответствует протоколу Hashable с использованием Generics. Этот код выглядит следующим образом:.

func uniqueElementsFrom<T: Hashable>(array: [T]) -> [T] { 
    var set = Set<T>() 
    let result = array.filter { 
    guard !set.contains($0) else { 
     return false 
    } 
    set.insert($0) 
    return true 
    } 
    return result 
} 

<T: Hashable> бит после имени функции говорит «Остальная часть этой функции будет относиться к типу T, который неопределенные Единственное, что вы можете быть уверены в том, что тип T будет соответствовать протоколу Hashable ».

Эта форма функции uniqueElementsFrom(array:) будет работать на любом массиве, который содержит элементы Hashable.

+0

Помогло бы это, если у меня есть массив объектов? И мне нужно отфильтровать ту же широту-долготу, которая содержится внутри объекта? –

+0

@ LohithKorupolu, да, вы могли бы использовать тот же подход. Объекты CLLocation Equable, поэтому вы можете сделать свой массив объектов CLLocations и сравнить их с помощью '=='. Обратите внимание, однако, что местоположения должны быть ТОЧНО одинаковыми. Если вы пытаетесь сказать, что несколько показаний GPS представляют одно и то же местоположение, использование '==' для сравнения местоположений не будет работать, потому что местоположения будут отличаться небольшим количеством. –

Смежные вопросы