Find Duplicate Elements In Array Using Swift

2019-01-10 15:34发布

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 6 integers. then i should print them out.

10条回答
虎瘦雄心在
2楼-- · 2019-01-10 15:58

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.

查看更多
叛逆
3楼-- · 2019-01-10 15:59

I've found a way by using reduce, here is the code(Swift 4):

let testNumbers = [1,1,2,3,4,5,2]
let nondupicate = testNumbers.reduce(into: [Int]()) {
    if !$0.contains($1) {
        $0.append($1)
    } else {
        print("Found dupicate: \($1)")
    }
}

As a side effect, it returns an array has no dupicated elements.

You can easily modify it for counting duplicated elements numbers, checking string arrays etc.

查看更多
4楼-- · 2019-01-10 16:00

To filter an array based on properties, you can use this method:

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
    }
}

Which you can call as followed, based on the contacts example of Rob:

let filteredContacts = myContacts.filterDuplicates { $0.name == $1.name && $0.phone == $1.phone }
查看更多
一纸荒年 Trace。
5楼-- · 2019-01-10 16:02

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)
   }

}
查看更多
Deceive 欺骗
6楼-- · 2019-01-10 16:04

Antoine's solution in Swift 3+ syntax

extension Array {

    func filterDuplicates(includeElement: @escaping (_ lhs: Element, _ rhs: Element) -> Bool) -> [Element] {

        var results = [Element]()

        forEach { (element) in

            let existingElements = results.filter {
                return includeElement(element, $0)
            }

            if existingElements.count == 0 {
                results.append(element)
            }
        }
        return results
    }
}
查看更多
何必那么认真
7楼-- · 2019-01-10 16:06

To find duplicates, you could build cross reference by phone number, then filter that down to duplicates only. For example, consider:

let contacts = [
    Contact(name: "Rob",     phone: "555-1111"),
    Contact(name: "Richard", phone: "555-2222"),
    Contact(name: "Rachel",  phone: "555-1111"),
    Contact(name: "Loren",   phone: "555-2222"),
    Contact(name: "Mary",    phone: "555-3333"),
    Contact(name: "Susie",   phone: "555-2222")
]

In Swift 4, you can build the cross reference dictionary with:

let crossReference = Dictionary(grouping: contacts, by: { $0.phone })

Or

let crossReference = contacts.reduce(into: [String: [Contact]]()) {
    $0[$1.phone, default: []].append($1)
}

Then, to find the duplicates:

let duplicates = crossReference
    .filter { $1.count > 1 }                 // filter down to only those with multiple contacts
    .sorted { $0.1.count > $1.1.count }      // if you want, sort in descending order by number of duplicates

Clearly use whatever model types make sense for you, but the above uses the following Contact type:

struct Contact {
    let name: String
    let phone: String
}

There are many, many ways to implement this, so I wouldn't focus on the implementation details of the above, but rather focus on the concept: Build cross reference original array by some key (e.g. phone number) and then filter results down to just those keys with duplicate values.


It sounds like you want to flatten this structure that reflects the duplicates, into a single array of contacts (I'm not sure why you'd want to do that, as you lose the structure identifying which are duplicates of each other), but if you want to do that, you can flatMap it:

let flattenedDuplicates = crossReference
    .filter { $1.count > 1 }                 // filter down to only those with multiple contacts
    .flatMap { $0.1 }                        // flatten it down to just array of contacts that are duplicates of something else

For Swift 2 or 3 renditions, see previous renditions of this answer.

查看更多
登录 后发表回答