javascript, sort 2 array dependently

后端 未结 6 616
渐次进展
渐次进展 2021-01-04 10:09

for hours i\'ve been trying to figure out how to sort 2 array dependently.

Let\'s say I have 2 arrays.

First one:

array1 = [\'zzzzz\', \'aaaa         


        
相关标签:
6条回答
  • 2021-01-04 10:24

    I would "zip" them into one array of objects, then sort that with a custom sort callback, then "unzip" them back into the two arrays you wanted:

    var array1 = ['zzzzz', 'aaaaaa', 'ccccc'],
        array2 = [3, 7, 1],
        zipped = [],
        i;
    
    for(i=0; i<array1.length; ++i) {
        zipped.push({
            array1elem: array1[i],
            array2elem: array2[i]
        });
    }
    
    zipped.sort(function(left, right) {
        var leftArray1elem = left.array1elem,
            rightArray1elem = right.array1elem;
    
        return leftArray1elem === rightArray1elem ? 0 : (leftArray1elem < rightArray1elem ? -1 : 1);
    });
    
    array1 = [];
    array2 = [];
    for(i=0; i<zipped.length; ++i) {
        array1.push(zipped[i].array1elem);
        array2.push(zipped[i].array2elem);
    }
    
    alert('Sorted arrays:\n\narray1: ' + array1 + '\n\narray2: ' + array2);
    

    Here's a working fiddle.

    0 讨论(0)
  • 2021-01-04 10:24

    Using a solution found here to find the new indices after sorting an array, you can apply those indices to array2 like so.

    function sortWithIndices(toSort) {
      for (var i = 0; i < toSort.length; i++) {
        toSort[i] = [toSort[i], i];
      }
      toSort.sort(function(left, right) {
        return left[0] < right[0] ? -1 : 1;
      });
      toSort.sortIndices = [];
      for (var j = 0; j < toSort.length; j++) {
        toSort.sortIndices.push(toSort[j][2]);
        toSort[j] = toSort[j][0];
      }
      return toSort;
    }
    
    
    var array1 = ['zzzz', 'aaaa', 'cccc'];
    var array2 = [3, 7, 1];
    
    // calculate the indices of array1 after sorting. (attached to array1.sortIndices)
    sortWithIndices(array1);
    
    // the final array after applying the sorted indices from array1 to array2
    var final = [];
    
    // apply sorted indices to array2
    for(var i = 0; i < array1.sortIndices.length; i++)
        final[i] = array2[array1.sortIndices[i]];
    
    // output results
    alert(final.join(","));
    

    JSFiddle Demo

    0 讨论(0)
  • 2021-01-04 10:26

    Instead of two arrays of primitive types (strings, numbers) you can make an array of objects where one property of the object is string (containing "aaaaa", "cccccc", "zzzzzz") and another is number (7,1,3). This way you will have one array only, which you can sort by any property and the other property will remain in sync.

    0 讨论(0)
  • 2021-01-04 10:26

    Assumption:

    • The arrays are the same length (this is implied by your question)
    • the contents can be compared with > and < (true in your example, but I wanted to make it clear that it was assumed here)

    So then we can use an insertion sort.

    var value,len = array1.length;
    for (i=0; i < len; i++) {
            value = array1[i];
            for (j=i-1; j > -1 && array1[j] > value; j--) {
                array1[j+1] = array1[j];
                array2[j+1] = array2[j];
            }
    
            items[j+1] = value;
     }
    
    0 讨论(0)
  • 2021-01-04 10:30

    Here's a simple function that will do the trick:

    function sortTogether(array1, array2) {
        var merged = [];
        for(var i=0; i<array1.length; i++) { merged.push({'a1': array1[i], 'a2': array2[i]}); }
        merged.sort(function(o1, o2) { return ((o1.a1 < o2.a1) ? -1 : ((o1.a1 == o2.a1) ? 0 : 1)); });
        for(var i=0; i<merged.length; i++) { array1[i] = merged[i].a1; array2[i] = merged[i].a2; }
    }
    

    Usage demo (fiddle here):

    var array1 = ['zzzzz', 'aaaaaa', 'ccccc'];
    var array2 = [3, 7, 1];
    console.log('Before..: ',array1,array2);
    
    sortTogether(array1, array2); // simply call the function
    
    console.log('After...: ',array1,array2);
    

    Output:

    Before..:  ["zzzzz", "aaaaaa", "ccccc"] [3, 7, 1]
    After...:  ["aaaaaa", "ccccc", "zzzzz"] [7, 1, 3] 
    
    0 讨论(0)
  • 2021-01-04 10:44

    It just so happens I had some old code lying around that might do the trick:

    function arrVirtualSortGetIndices(array,fnCompare){
        var index=array.map(function(e,i,a){return i;});
        fnCompare=fnCompare || defaultStringCompare;
        var idxCompare=function (aa,bb){return fnCompare(array[aa],array[bb]);};
        index.sort(idxCompare);
        return index;
    
        function defaultStringCompare(aa,bb){
            if(aa<bb)return -1;
            if(bb<aa)return 1;
            return 0;
        }
        function defaultNumericalCompare(aa,bb){
            return aa-bb;
        }   
    }
    
    function arrReorderByIndices(array,indices){
        return array.map(
            function(el,ix,ar){
                return ar[indices[ix]];
            }
        );
    }
    
    var array1 = ['zzzzz', 'aaaaaa', 'ccccc'];
    var array2 = [3, 7, 1];
    var indices=arrVirtualSortGetIndices(array1);
    var array2sorted=arrReorderByIndices(array2,indices);
    array2sorted;
    
    /*
    7,1,3
    */
    

    Sorry, I don't do 'fors'. At least not when I don't have to.

    And fiddle.


    Also, an alternative fiddle that sorts the results when given an array of objects like this:

    given:

    var list = [
        {str:'zzzzz',value:3},
        {str:'aaaaa',value:7},
        {str:'ccccc',value:1}
    ];
    

    outputs:

    [
      {str: "aaaaa", value: 7},
      {str: "ccccc", value: 1},
      {str: "zzzzz", value: 3}
    ]
    
    0 讨论(0)
提交回复
热议问题