Reputation: 571
I've a scenario where I have two arrays of tuples.
tuple1 = [(score1, index1), (score2, index2), (score3, index3)]
tuple2 = [(date1, index1), (date2, index2), (date3, index4)]
I want to get the scores and dates from these tuples and create a new array of tuples such that it contains the score and date having the same index like this:
tuple3 = [(score1, date1), (score2, date2)]
How can I implement this? What is the best practice to follow in this scenario? Note: The arrays can be of different sizes
My implementation for the scenario is as follows:
var tuple3 = [(Double, Date)]()
for (i,psa) in tuple1.enumerated() {
let date = tuple2.filter({ $0.1 == i })
if date.count == 1 {
let newTuple = (tuple1.0, date[0].0)
tuple3.append(newTuple)
}
}
Is this a right way to do it or is there a better one?
Upvotes: 0
Views: 866
Reputation: 1509
let tuple1 = [("score1", "index1"), ("score2", "index2"), ("score3", "index3")]
let tuple2 = [("date1", "index1"), ("date2", "index2"), ("date3", "index4")]
let t2Dict = tuple2.reduce(into: [String:String]()) { (dict, args) in
let (date, index) = args
dict[index] = date
}
let tuple3 = tuple1.compactMap { args -> (String, String)? in
let (score, index) = args
guard let date = t2Dict[index] else { return nil }
return (score, date)
}
It's not as pretty as the others, but it's far more efficient to collapse one of the tuples into a dictionary first.
Upvotes: 2
Reputation: 18591
This might be what you're looking for:
let tuple1 = [("score1", "index1"), ("score2", "index2"), ("score3", "index3")]
let tuple2 = [("date1", "index1"), ("date2", "index2"), ("date3", "index4")]
let filtered = tuple1.filter {tuple2.map{$0.1}.contains($0.1)}
let result = filtered.map {tuple in
return (tuple.0, tuple2.first(where: {$0.1 == tuple.1})!.0)
}
print (result) // [("score1", "date1"), ("score2", "date2")]
I'm using Strings for simplicity, just make sure you are using Equatable objects in your tuples.
Upvotes: 0
Reputation: 26036
This should do the trick:
let tuple3 = tuple1.compactMap({ (scoreInTuple1, indexInTuple1) -> (String, String)? in
if let tupleIn2 = tuple2.first(where: { (scoreInTuple2, index2InTuple2) in index2InTuple2 == indexInTuple1 }){
return (scoreInTuple1, tupleIn2.0)
}
return nil
})
(String, String)
should be change to the real type/class of score
& date1
.
Also, index2InTuple2 == indexInTuple1
might be changed also if it's custom type/class which might not be Equatable
.
With sample code before:
let tuple1 = [("score1", "index1"), ("score2", "index2"), ("score3", "index3")]
let tuple2 = [("date1", "index1"), ("date2", "index2"), ("date3", "index4")]
Debug log after:
print("tuple3: \(tuple3)")
Output:
$> tuple3: [("score1", "date1"), ("score2", "date2")]
Upvotes: 0
Reputation: 100523
You can try
let v1 = [("1","2"),("3","4")]
let v2 = [("1A","2A"),("3A","4A")]
let res = zip(v1,v2).map { ($0.0 , $1.0) } // [("1", "1A"), ("3", "3A")]
print(res)
Upvotes: 3