19

I haven't found anything on that in Swift. Have found how to find unique values on an array, but not this. Sorry if it sounds quite basic...

But I have the following array

var selectedValues = [String]()

And the following value that comes from a Parse query

 var objectToAppend = object.objectForKey("description")! as! String

this is how I'am doing it at the moment.

self.selectedHobbies.append(objectToAppend)

But because the query happens repeated times, it ends up appending repeated values. It works, but I just want to not waste memory and only keep unique values.

Any ideas on how to solve that in swift?

2 Answers 2

33

You can use a Set which guarantees unique values.

var selectedValues = Set<String>()
// ...
selectedValues.insert(newString) // will do nothing if value exists

Of course, the elements of a Set are not ordered.

If you want to keep the order, just continue with the Array but check before you insert.

if !selectedValues.contains("Bar") { selectedValues.append("Bar") }
Sign up to request clarification or add additional context in comments.

5 Comments

is it possible to maintain your code syntax but use a [String] instead of a Set<String>? A Set<String> do not have much use for me as I can convert it to a [String]. I tried much haven't got much luck with it.
@Mundi You don't need to do a contains check. If you insert and the element already exists, nothing will happen.
@Alexander Agree. Changed it.
You can also ignore what you put into the array and just use .unique when you need only the unique values. In some cases this might be preferable, like if the unique check is costly and saving the data isn't.
Set works with Hashable types only. So for example Set<String> works but Set<SomeProtocol> doesn't
9

I guess that your problem was resolved but I add my answer for next developers who's facing same problem :)

My solution is to write an extension of Array to add elements from an array with a distinct way:

here the code :

extension Array{
    public mutating func appendDistinct<S>(contentsOf newElements: S, where condition:@escaping (Element, Element) -> Bool) where S : Sequence, Element == S.Element {
      newElements.forEach { (item) in
        if !(self.contains(where: { (selfItem) -> Bool in
            return !condition(selfItem, item)
        })) {
            self.append(item)
        }
    }
  }
}

example:

var accounts: [Account]
let arrayToAppend: [Account]
accounts.appendDistinct(contentsOf: arrayToAppend, where: { (account1, account2) -> Bool in
        return account1.number != account2.number
})

3 Comments

Hi, I have a question. I customized your code like this: public mutating func appendDistinct<T>(_ newElement: T, where condition: @escaping (Element) -> Bool) where T == Element { if !(self.contains(where: { (newElement) -> Bool in return !condition(newElement) })) { self.append(newElement) } } However, it shows a warning: "Same-type requirement makes generic parameters 'T' and 'Element' equivalent; this is an error in Swift 6." How can I fix this issue and get the correct code?
Hi @Kaaaaai, I think in this case we don't need to use generic type in this method. The method could be simply like this: ` public mutating func appendDistinct(_ newElement: Element, where condition: @escaping (Element) -> Bool) { if !(self.contains(where: { (newElement) -> Bool in return !condition(newElement) })) { self.append(newElement) } } `
that's helpful,thank you~

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.