Removing duplicate elements from an array in Swift

后端 未结 30 2010
遥遥无期
遥遥无期 2020-11-22 00:07

I might have an array that looks like the following:

[1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]

Or, reall

30条回答
  •  醉话见心
    2020-11-22 01:02

    For arrays where the elements are neither Hashable nor Comparable (e.g. complex objects, dictionaries or structs), this extension provides a generalized way to remove duplicates:

    extension Array
    {
       func filterDuplicate(_ keyValue:(Element)->T) -> [Element]
       {
          var uniqueKeys = Set()
          return filter{uniqueKeys.insert(keyValue($0)).inserted}
       }
    
       func filterDuplicate(_ keyValue:(Element)->T) -> [Element]
       { 
          return filterDuplicate{"\(keyValue($0))"}
       }
    }
    
    // example usage: (for a unique combination of attributes):
    
    peopleArray = peopleArray.filterDuplicate{ ($0.name, $0.age, $0.sex) }
    
    or...
    
    peopleArray = peopleArray.filterDuplicate{ "\(($0.name, $0.age, $0.sex))" }
    

    You don't have to bother with making values Hashable and it allows you to use different combinations of fields for uniqueness.

    Note: for a more robust approach, please see the solution proposed by Coeur in the comments below.

    stackoverflow.com/a/55684308/1033581

    [EDIT] Swift 4 alternative

    With Swift 4.2 you can use the Hasher class to build a hash much easier. The above extension could be changed to leverage this :

    extension Array
    {
        func filterDuplicate(_ keyValue:((AnyHashable...)->AnyHashable,Element)->AnyHashable) -> [Element]
        {
            func makeHash(_ params:AnyHashable ...) -> AnyHashable
            { 
               var hash = Hasher()
               params.forEach{ hash.combine($0) }
               return hash.finalize()
            }  
            var uniqueKeys = Set()
            return filter{uniqueKeys.insert(keyValue(makeHash,$0)).inserted}     
        }
    }
    

    The calling syntax is a little different because the closure receives an additional parameter containing a function to hash a variable number of values (which must be Hashable individually)

    peopleArray = peopleArray.filterDuplicate{ $0($1.name, $1.age, $1.sex) } 
    

    It will also work with a single uniqueness value (using $1 and ignoring $0).

    peopleArray = peopleArray.filterDuplicate{ $1.name } 
    

提交回复
热议问题