Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Swift how can I sort one array based on another array?

In Swift, say I have two arrays:

var array1: [Double] = [1.2, 2.4, 20.0, 10.9, 1.5]
var array2: [Int] = [1, 0, 2, 0, 3]

Now, I want to sort array1 in ascending order and reindex array2 accordingly so that I get

array1 = [1.2, 1.5, 2.4, 10.9, 20.4]
array2 = [1, 3, 0, 0, 2]

Is there a simple way to do this using Swift functions or syntax?

I know I can build a function to do it and can keep track of indices, but I'm curious if there is a more elegant solution.

like image 485
user3731622 Avatar asked Nov 08 '15 00:11

user3731622


People also ask

How do I sort an array in a specific range?

sort(byte[] a, int fromIndex, int toIndex) method sorts the specified range of the specified array of bytes into ascending numerical order. The range to be sorted extends from index fromIndex, inclusive, to index toIndex, exclusive.

How do you sort an array and assign it to another array in Java?

You can sort within the array using Arrays. sort() method, or if you want to sort in a different array, you can take following steps: Copy the array to new array. Sort the new array and then sort.


Video Answer


2 Answers

let array1: [Double] = [1.2, 2.4, 20.0, 10.9, 1.5]
let array2: [Int] = [1, 0, 2, 0, 3]

// use zip to combine the two arrays and sort that based on the first    
let combined = zip(array1, array2).sorted {$0.0 < $1.0}
print(combined) // "[(1.2, 1), (1.5, 3), (2.4, 0), (10.9, 0), (20.0, 2)]"

// use map to extract the individual arrays    
let sorted1 = combined.map {$0.0}
let sorted2 = combined.map {$0.1}

print(sorted1)  // "[1.2, 1.5, 2.4, 10.9, 20.0]"
print(sorted2)  // "[1, 3, 0, 0, 2]"

Sorting more than 2 arrays together

If you have 3 or more arrays to sort together, you can sort one of the arrays along with its offsets, use map to extract the offsets, and then use map to order the other arrays:

let english = ["three", "five", "four", "one", "two"]
let ints = [3, 5, 4, 1, 2]
let doubles = [3.0, 5.0, 4.0, 1.0, 2.0]
let roman = ["III", "V", "IV", "I", "II"]

// Sort english array in alphabetical order along with its offsets
// and then extract the offsets using map
let offsets = english.enumerated().sorted { $0.element < $1.element }.map { $0.offset }

// Use map on the array of ordered offsets to order the other arrays
let sorted_english = offsets.map { english[$0] }
let sorted_ints = offsets.map { ints[$0] }
let sorted_doubles = offsets.map { doubles[$0] }
let sorted_roman = offsets.map { roman[$0] }

print(sorted_english)
print(sorted_ints)
print(sorted_doubles)
print(sorted_roman)

Output:

["five", "four", "one", "three", "two"]
[5, 4, 1, 3, 2]
[5.0, 4.0, 1.0, 3.0, 2.0]
["V", "IV", "I", "III", "II"]
like image 113
vacawama Avatar answered Sep 28 '22 07:09

vacawama


You could "link" the items of each array by mapping over the indices to create an array of tuples, then sort the tuples according to the first array's values before extracting the original arrays.

assert(array1.count == array2.count, "The following technique will only work if the arrays are the same length.")
let count = array1.count

// Create the array of tuples and sort according to the
// first tuple value (i.e. the first array)
let sortedTuples = (0..<count).map { (array1[$0], array2[$0]) }.sort { $0.0 < $1.0 }

// Map over the sorted tuples array to separate out the
// original (now sorted) arrays.
let sortedArray1 = sortedTuples.map { $0.0 }
let sortedArray2 = sortedTuples.map { $0.1 }
like image 23
Stuart Avatar answered Sep 28 '22 06:09

Stuart