Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
620 views
in Technique[技术] by (71.8m points)

function - How can I sort multiple arrays based on the sorted order of another array

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"]
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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) }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...