-2

I have an array which has repeated items, i want to get unique items only so i did this:

    let decoded  = userDefaults.object(forKey: "shifts") as! Data
    myShifts = NSKeyedUnarchiver.unarchiveObject(with: decoded) as! [Shift]
    filtered_shifts = myShifts.filter{$0.regionName == region && $0.cityName == city && $0.idService == idservice && $0.quantityStaff != 0}
    for shift in filtered_shifts {
        let decoded4  = userDefaults.object(forKey: "nationalities") as! Data
        let decodedNationalities = NSKeyedUnarchiver.unarchiveObject(with: decoded4) as! [Nationality]
        for nationality in decodedNationalities {
            if nationality.id == shift.idNationality{
                nationalitiesid.append(nationality.id)
                nationalities.append(nationality.name)
            }
        }
    }
    uniqueNationality = Array(Set(nationalities))
    uniqueNationalityid = Array(Set(nationalitiesid))

which is getting me a new array with unique items as i need...

the problem is that the order is diferent when i want the same order ... for exampple:

nationalitiesid = [3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4]

nationalities = ["Indian", "Indian", "Indian", "Indian", "Indian", "Indian", "Indian", "Indian", "Philippines", "Philippines", "Philippines", "Philippines"]

the unique array is:

uniqueNationality = ["Indian", "Philippines"]

uniqueNationalityid = [4, 3]

and this is wrong since Indian id is 3 and Philippines id is 4!

it should be:

uniqueNationalityid = [3, 4]

How to solve this?

Community
  • 1
  • 1
mrs.bassim
  • 469
  • 2
  • 7
  • 16

3 Answers3

4
let uniqueList = nationalities.reduce([], {
    $0.contains($1) ? $0 : $0 + [$1]
})
U. Benlice
  • 901
  • 9
  • 14
0

This does not directly answer the question. This is an alternative solution. Using a model to group the related information rather keeping two separate arrays in sync.

For more information on Structs and Classes check the documentation

struct Nationality {
    var id: Int
    var name: String
}

let nationalities = [
    Nationality(id: 3, name: "Indian"),
    Nationality(id: 4, name: "Philippines")
]

let randomNationalityIds = [3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4]
let nationalitiesResult = Set(randomNationalityIds).flatMap { id in
    nationalities.filter({ id == $0.id }).first
}

print(nationalitiesResult)

Output: [__lldb_expr_136.Nationality(id: 4, name: "Philippines"), __lldb_expr_136.Nationality(id: 3, name: "Indian")]

You don't need to keep these in order because the id and name are in the same place.

Scriptable
  • 19,402
  • 5
  • 56
  • 72
0

Instead of creating a non-unique array first and reducing it to a unique array afterwards you could as well collect the nationality strings in a Set of Nationalities:

var nationalitySet = Set<String>()
...
for nationality in decodedNationalities {
    nationalitySet.append(nationality)
}

A set won’t store any duplicates so if you add a nationality which is already contained it won’t be added again.

As the set is unordered but converting it into a sorted array is an easy one:

let nationalities = nationalitiesSet.sorted { $0.name < $1.name }

This solution does, however, require Nationality to be hashable, i. e. it must conform to the Hashable protocol:

struct Nationality: Hashable {
    var name: String
    var id: Int
}
Tom E
  • 1,530
  • 9
  • 17