Reputation: 19602
I am trying to sort an array of tuples using sorted
.
The error I get is:
Cannot invoke 'sorted' with an argument list of type (((MyClass1, MyClass2)) -> Bool)
The array is created like this:
class MyClass1 {
var id: Int
init(id:Int) { self.id = id }
}
class MyClass2 {
var id2: Int
init(id2:Int) { self.id2 = id2 }
}
let array1 = [MyClass1(id:4), MyClass1(id:3), MyClass1(id:2), MyClass1(id:1)]
let array2 = [MyClass2(id2:1), MyClass2(id2:2), MyClass2(id2:3), MyClass2(id2:4)]
var tuples = zip(array1, array2)
What I have tried:
tuples = tuples.sorted { (left, right) -> Bool in
return left.1.id2 > right.1.id2
}
tuples = tuples.sorted { $0.1.id2 > $1.1.id2 }
tuples = tuples.sorted(by: { (first: (MyClass1, MyClass2), second: (MyClass1, MyClass2)) -> Bool in
return first.1.id2 > second.1.id2
})
The expected output is(pseudo, handwritten):
[(myClass1WithId_1, myClass2WithId2_4),(myClass1WithId_2, myClass2WithId2_3),(myClass1WithId_3, myClass2WithId2_2),(myClass1WithId_4, myClass2WithId2_1)]
The tuples sorted by myClass2.id2 descending.
Update
I found out how to workaround the issue. The error seems to be wrong/misleading.
I can sort it when assigning the result to a new variable:
let tuples2 = tuples.sorted { (left, right) -> Bool in
return left.1.id2 > right.1.id2
}
while assigning it to the existing variable gives me the mentioned error:
tuples = tuples.sorted { (left, right) -> Bool in
return left.1.id2 > right.1.id2
}
Upvotes: 2
Views: 260
Reputation: 535087
I am trying to sort an array of tuples
But problem is that your tuples
is not an array. (It is a thing called a Zip2Sequence.) The solution is to coerce it to an array:
var tuples = Array(zip(array1, array2))
Now your original code will work:
let array1 = [MyClass1(id:4), MyClass1(id:3), MyClass1(id:2), MyClass1(id:1)]
let array2 = [MyClass2(id2:1), MyClass2(id2:2), MyClass2(id2:3), MyClass2(id2:4)]
var tuples = Array(zip(array1, array2)) // *
tuples = tuples.sorted { (left, right) -> Bool in
return left.1.id2 > right.1.id2
}
The reason your solution worked is that a sorted sequence yields an array. So you can't reassign the array to the sequence variable (tuples
) but you can assign it to a different variable (tuples2
). My solution starts with an array, so the resulting sorted array can be assigned back to the same variable.
Upvotes: 1
Reputation: 63197
You're not able to use sorted()
because the tuple type (MyClass1, MyClass2)
does not conform to Comparable
, so the sorter would not know how to sort your tuples. You can't add an extension that adds conformance to it either, because tuples can't have extensions or conform to protocols.
You can however, use sorted(by:)
, which requires you give a closure which defines the sorting between elements.
class MyClass1 {
var id: Int
init(id:Int) { self.id = id }
}
class MyClass2 {
var id2: Int
init(id2:Int) { self.id2 = id2 }
}
let array1 = [MyClass1(id:4), MyClass1(id:3), MyClass1(id:2), MyClass1(id:1)]
let array2 = [MyClass2(id2:1), MyClass2(id2:2), MyClass2(id2:3), MyClass2(id2:4)]
let tuples = zip(array1, array2)
let sortedTuples = tuples.sorted{ $0.1.id2 > $1.1.id2 }
print(sortedTuples)
Upvotes: 0