Find Duplicate Elements In Array Using Swift

后端 未结 12 1363
说谎
说谎 2020-11-29 01:42

How to find Duplicate Elements in Array? I have array of phone numbers so in the phone numbers i should start searching from the right side to the left side and find similar

相关标签:
12条回答
  • 2020-11-29 01:55

    You could implement it using "Merge sort", but you need to make one modification, during the merge step you should ignore the duplicates.

    The easiest way to find duplicate elements is if the phone number is just a 6-digit number and has type Int, you could sort the array of phone numbers and than filter that to find duplicates.

    var phoneNumbers = [123456, 234567, 345678, 123456, 456789, 135790, 456789, 142638]
    
    func findDuplicates(sortedArray array: [Int]) -> [Int]
    {
        var duplicates: [Int] = []
    
        var prevItem: Int = 0
        var addedItem: Int = 0
    
        for item in array
        {
            if(prevItem == item && addedItem != item)
            {
                duplicates.append(item)
                addedItem = item
            }
    
            prevItem = item
        }
    
        return duplicates
    }
    
    func sortPhoneNumbers(phoneNumbers: [Int]) -> [Int]
    {
        return phoneNumbers.sorted({ return $0<$1 })
    }
    
    sortPhoneNumbers(phoneNumbers)
    findDuplicates(sortPhoneNumbers(phoneNumbers))
    

    In addition, you could implement the findDuplicates method in different ways:

    Using Set (Swift 1.2+):

    func findDuplicates(array: [Int]) -> [Int]
    {
        var duplicates = Set<Int>()
        var prevItem = 0       
    
        for item in array
        {
            if(prevItem == item)
            {
                duplicates.insert(item)
            }
    
            prevItem = item
        }
    
        return Array(duplicates)
    }
    

    And so on.

    0 讨论(0)
  • 2020-11-29 01:56

    Based on Rob's answer, an array extension to just finds duplicates is:

    extension Array where Element: Hashable {
        func duplicates() -> Array {
            let groups = Dictionary(grouping: self, by: {$0})
            let duplicateGroups = groups.filter {$1.count > 1}
            let duplicates = Array(duplicateGroups.keys)
            return duplicates
        }
    }
    
    0 讨论(0)
  • 2020-11-29 01:56

    A very simple answer which preserves all duplicates

    let originalNums = [5, 3, 2, 3 , 7 , 5,3]
    var nums = Array(originalNums)
    
    let numSet = Set(nums)
    
    for num in numSet {
      if let index = nums.index(of: num) {
         nums.remove(at: index)
      }
    }
    

    output

    [3, 5, 3]
    
    0 讨论(0)
  • 2020-11-29 01:57

    Same as in @tikhop's answer, but as Array extension (Swift 3):

    extension Array where Element: Comparable & Hashable {
    
       public var duplicates: [Element] {
    
          let sortedElements = sorted { $0 < $1 }
          var duplicatedElements = Set<Element>()
    
          var previousElement: Element?
          for element in sortedElements {
             if previousElement == element {
                duplicatedElements.insert(element)
             }
             previousElement = element
          }
    
          return Array(duplicatedElements)
       }
    
    }
    
    0 讨论(0)
  • 2020-11-29 02:03

    I also had a similar problem and have overcome in the following way. (Xcode 8.3.2)

    let a = [123456, 234567, 345678, 123456, 456789, 135790, 456789, 142638]
    var b = a // copy-on-write so that "a" won't be modified
    
    while let c = b.popLast() {
      b.forEach() {
        if $0 == c {
          Swift.print("Duplication: \(c)")
        }
      }
    }
    
    //  Duplication: 456789
    //  Duplication: 123456
    

    The point is that the number of comparison. It would be smaller than others.

    Assume that the number of items in the array is N. In each loop, the number will be decrementing by one. So, the total number will be (N-1) + (N-2) + (N-3) + ... + 2 + 1 = N * (N-1) / 2 When N = 10, that will be 9 + 8 + ... = 45

    In contrast, that of some algorithms might be N * N. When N = 10 that will be 100.

    In spite of that, taking into account of the cost of deep-copy or shallow-copy, I agree that @Patrick Perini's brilliant way would be better than this in some situations even the number of that would be N * N.

    EDIT:

    Alternative way with IteratorProtocol

    let a = [123456, 234567, 345678, 123456, 456789, 135790, 456789, 142638]
    var i = a.makeIterator()
    
    while let c = i.next() {
      var j = i
      while let d = j.next() {
        if c == d {
          Swift.print("Duplication: \(c)")
        }
      }
    }
    
    //  Duplication: 123456
    //  Duplication: 456789
    

    That looks more complex, but uses the same idea as before. This does not have unnecessary memory allocations or copies.

    My concern is efficiency, i.e. quicker UI response, longer battery life, smaller memory footprint, etc. Avoiding unnecessary memory allocations and/or memory copies which are automatically done by Swift in the behind scene would be crucial if we are providing competitive products. (-;

    0 讨论(0)
  • 2020-11-29 02:13

    Feeling ~clever~. Given an array of Ints

    let x = [1, 1, 2, 3, 4, 5, 5]
    let duplicates = Array(Set(x.filter({ (i: Int) in x.filter({ $0 == i }).count > 1})))
    // [1, 5]
    

    Please note, this is horrendously efficient for everyone involved, including the compiler, and you.

    I'm just showing off.

    Edit: lol someone downvoted this, which leads me to reiterate, just in case: please DO NOT USE THIS in production or anywhere else.

    0 讨论(0)
提交回复
热议问题