0

I have an array of objects with some properties.

Ex: Restaurants {name, latitude, longitude, address}

I want to compare each object based on a particular property and return a list of distinct objects.

For example:

Array = [R1, R2, R3, R4, R5]

Let say, Restaurants R4 and R5 are closer to each other and they have the same latitude and longitude.

I need to compare and filter the array

($0.latitude == $1.latitude and $0.longitude == $1.longitude) rounded to 3 decimal points

so that the final result will have the following items [R1, R2, R3, R4]

2 Answers 2

2

As @kandelvijaya said, if you want/have to compare elements pairwise I'm not sure you can do better than quadratic time (which is fine in many cases).

Here's a generic O(n) alternative. Two things:

  • Instead of comparing two elements directly you provide a key representing the property that you want to compare by.
  • This key needs to be hashable (wich many standard types are).

.

extension Sequence {
    typealias Element = Iterator.Element

    func uniqued<Key: Hashable>(by key: (Element) -> (Key)) -> [Element] {
        var seen = Set<Key>()
        return filter {
            seen.update(with: key($0)) == nil
        }
    }
}

Usage:

let numbers = [1, 1, 1, 2, 2, 3, 1, 2, 3]
let uniqueByValue = numbers.uniqued { $0 } 

let strings = ["a", "b", "aa", "bb", "ccc", "dddd"]
let uniqueByLength = strings.uniqued { $0.characters.count }

In your case this could be:

let restaurantes = [R1, R2, R3, R4, R5]
let uniques = restaurants.uniqued { 
    let roundedLat = ...
    let roundedLong = ...
    return "\(roundedLat), \(roundedLong)"
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Arthur. Couldnt try out your solutions. Will check it later
1
class B {
    var a: String?
    var b: Int?
}

var arr:[B] = []

arr.filter{ index in
    var repeatedCount = 0
    arr.forEach{
        repeatedCount += $0.a == index.a ? 1 : 0
    }
    return repeatedCount == 1
}

The above solution will work but the complexity is o(arr.count^2) which is bad for large sets of items.

You can generalize the algorithm and make it efficient. Or make a extension function on Array distinct

In your case the code would be something like this:

arr.filter{ index in
    var repeatedCount = 0
    arr.forEach{
        if $0.latitude == index.latitude && $0.longitude == index.longitude {
            repeatedCount += 1
        }
    }
    return repeatedCount == 1
}

1 Comment

Thanks @kandelvijaya. Minor update - instead of repeatedCount += 0 we need repeatedCount += 1 right?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.