PoisonedApps
PoisonedApps

Reputation: 726

Identify Duplicates In Array

I have an array of custom objects and want to know how to identify which objects are duplicates. I know how to remove the duplicates but that is not functionality I'm after. Im using swift 2.

Example:

var movies: [Movie] = ["Batman v Superman: Dawn of Justice", "Batman v Superman: Dawn of Justice", "Deadpool"," "Deadpool", "Hardcore Henry", "Jason Bourne", "Jurassic World"]

So i want to show a table view with the list of movies above but with "Batman" and "Deadpool" highlighted.

For more clarity on what I'm trying to achieve look at the screenshot. I have a list of movies that two users select in a previous view controller. I want to display the selected movies in a table view. I want to specifically show if there were movies that both people selected.

enter image description here

Upvotes: 2

Views: 5416

Answers (4)

dfrib
dfrib

Reputation: 73236

I generally try to avoid posting answers with code entirely written by someone else (MIT License), but the reference below is such a neat fit for this question that I believe it's worth including as an answer.


The solution use the same technique as the accepted answer, but on a more general form (made compact with a neat subscript extension to Dictionary): the freq() dictionary extension from GitHub user oisdk's excellent SwiftSequence framework (MIT License):

/* ---------------------------------------------------------------------------
   source: GitHub user oisdk:
   https://github.com/oisdk/SwiftSequence/blob/master/Sources/Categorise.swift */
private extension Dictionary {
  subscript(key: Key, or or: Value) -> Value {
    get { return self[key] ?? or }
    set { self[key] = newValue }
  }
}

public extension SequenceType where Generator.Element : Hashable {
  // MARK: Frequencies

  /** 
  Returns a dictionary where the keys are the elements of self, and
  the values are their respective frequencies 
  ```swift
  [0, 3, 0, 1, 1, 3, 2, 3, 1, 0].freqs()
  // [2: 1, 0: 3, 3: 3, 1: 3]
  ```
  */
  @warn_unused_result
  func freqs() -> [Generator.Element:Int] {
    var freqs: [Generator.Element:Int] = [:]
    for el in self { freqs[el, or: 0] += 1 }
    return freqs
  }
}
/* --------------------------------------------------------------------------- */

/* example usage */
let movies = ["Batman","Batman","Flash","Avengers"]
print(movies.freqs()) // ["Avengers": 1, "Flash": 1, "Batman": 2]

Have a look at the framework for lots of other sequence goodies:

Upvotes: 3

tech4242
tech4242

Reputation: 2468

Based on your comment I have made a simple example with string arrays, which can easily be converted to your movie type:

let movies = ["Batman","Batman","Flash","Avengers"]
var movieCounts:[String:Int] = [:]    
for movie in movies {
 movieCounts[movie] = (movieCounts[movie] ?? 0) + 1
}

And you can test it like so:

for (key, value) in movieCounts {
 print("\(key) has been selected \(value) time/s")
}

Upvotes: 6

Frank
Frank

Reputation: 7595

Not sure what functionalities you want to make.

If just for list of items, you can use swift dictionary to count duplicates, by using movie name as key and count as value starting by 0.

If you want to highlight, you can use different style when you populate the table in the delegate method by checking if the item has duplicates.

Upvotes: 0

omarzl
omarzl

Reputation: 1029

Why not adding an id in the Movie object

and compare the two arrays searching the same object.

public class Movie:Equatable{
    var id=NSUUID().UUIDString
}

public func ==(lhs: Movie, rhs: Movie) -> Bool{
    return lhs.id == rhs.id
}

Comparing the arrays:

    var moviesA=[Movie]()
    var moviesB=[Movie]()

    var sharedMovies=[Movie]()
    for movie in moviesA{
        if moviesB.contains(movie){
            sharedMovies.append(movie)
        }
    }

Upvotes: 0

Related Questions