1

I have multiple arrays, and I want to sort all of them based on the sorted order of one of them, like so:

var myArr = ["b", "a", "c"]
var myArr2 = ["letter b", "letter a", "letter c"]
var myArr3 = ["b is the second letter", "a is the first letter", "c is the third letter"]

func sortMultipleArraysBasedOnOne(alphabeticallyArray:Array, arrays:[Array]){
  //order myArr alphabetically
  for array in arrays{
    //change all arrays indexes like in myArr
  }
}

sortMultipleArraysBasedOnOne(myArr, [myArr2, myArr3])

I expect after function execution the arrays will be like this:

myArr = ["a", "b", "c"]
myArr2 = ["letter a", "letter b", "letter c"]
myArr3 = ["a is the first letter", "b is the second letter", "c is the third letter"]

2 Answers 2

6

You can do this by first sorting an array of the keying array’s indices by the values they index, then generating new arrays based on those sorted indices, using PermutationGenerator:

let myArr = ["b", "a", "c"]
let myArr2 = ["letter b", "letter a", "letter c"]
let myArr3 = ["b is the second letter", "a is the first letter", "c is the third letter"]

func sortByKeyArray(keyArray: [String], valuesArrays: [[String]]) -> [[String]] {

    precondition(reduce(valuesArrays, true) { $0.0 && ($0.1.count == keyArray.count)},
        "Arrays all need to be the same length")


    let permutation = sorted(indices(keyArray)) {
        keyArray[$0] < keyArray[$1]
    }

    return valuesArrays.map {
        Array(PermutationGenerator(elements: $0, indices: permutation))
    }
}

sortByKeyArray(myArr, [myArr2, myArr3])
// returns [["letter a", "letter b", "letter c"], ["a is the first letter", "b is the second letter", "c is the third letter"]]

If you want to make this generic on any kind of collection (but still returning an array, in the same style as the std lib collection algos):

func sortByKeyingCollection<C: CollectionType, D: SequenceType 
  where D.Generator.Element == C, 
        C.Index: RandomAccessIndexType, 
        C.Generator.Element: Comparable>
(key: C, values: D) -> [[C.Generator.Element]] {

    let permutation = sorted(indices(key)) {
        key[$0] < key[$1]
    }

    return map(values) {
        Array(PermutationGenerator(elements: $0, indices: permutation))
    }
}

And a version that takes a custom comparator:

func sortByKeyingCollection<C: CollectionType, D: SequenceType where D.Generator.Element == C, C.Index: RandomAccessIndexType>(key: C, values: D, isOrderedBefore: (C.Generator.Element,C.Generator.Element)->Bool) -> [[C.Generator.Element]] {

    let permutation = sorted(indices(key)) {
        isOrderedBefore(key[$0],key[$1])
    }

    return map(values) {
        Array(PermutationGenerator(elements: $0, indices: permutation))
    }
}


sortByKeyingCollection(myArr, [myArr2, myArr3], >)
sortByKeyingCollection(myArr, [myArr2, myArr3], lexicographicalCompare)
sortByKeyingCollection(myArr, [myArr2, myArr3]) { dropFirst($0) < dropFirst($1) }
Sign up to request clarification or add additional context in comments.

1 Comment

can you edit it for Swift 2.1 with Int example 1,2,3 ?
-1

From what I understand, you want to order your array alphabetically. If so, you can use one of the example below :

Example 1

var anArray1 = ["b","a","d","e","c"]

func alphabeticallyOrder(lt : String, rt: String) -> Bool {
    return lt < rt
}

anArray1 = sorted(anArray1, alphabeticallyOrder)

println(anArray1) // [a, b, c, d, e]

Example 2

var anArray2 = ["b","a","d","e","c"]

anArray2 = sorted(anArray2, {$0 < $1})

println(anArray2) // [a, b, c, d, e]

Example 3

var anArray3 = ["b","a","d","e","c"]

anArray3 = sorted (anArray3 , <)

println(anArray3) // [a, b, c, d, e]

Edit : My bad, you also want to change the other arrays indexes in the process. I'll edit later if required.

Comments

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.