How do you sort an array on multiple columns?

前端 未结 16 1113
面向向阳花
面向向阳花 2020-11-22 13:02

I have a multidimensional array. The primary array is an array of

[publicationID][publication_name][ownderID][owner_name] 

What I am tryin

相关标签:
16条回答
  • 2020-11-22 13:52

    Came across a need to do SQL-style mixed asc and desc object array sorts by keys.

    kennebec's solution above helped me get to this:

    Array.prototype.keySort = function(keys) {
    
    keys = keys || {};
    
    // via
    // https://stackoverflow.com/questions/5223/length-of-javascript-object-ie-associative-array
    var obLen = function(obj) {
        var size = 0, key;
        for (key in obj) {
            if (obj.hasOwnProperty(key))
                size++;
        }
        return size;
    };
    
    // avoiding using Object.keys because I guess did it have IE8 issues?
    // else var obIx = function(obj, ix){ return Object.keys(obj)[ix]; } or
    // whatever
    var obIx = function(obj, ix) {
        var size = 0, key;
        for (key in obj) {
            if (obj.hasOwnProperty(key)) {
                if (size == ix)
                    return key;
                size++;
            }
        }
        return false;
    };
    
    var keySort = function(a, b, d) {
        d = d !== null ? d : 1;
        // a = a.toLowerCase(); // this breaks numbers
        // b = b.toLowerCase();
        if (a == b)
            return 0;
        return a > b ? 1 * d : -1 * d;
    };
    
    var KL = obLen(keys);
    
    if (!KL)
        return this.sort(keySort);
    
    for ( var k in keys) {
        // asc unless desc or skip
        keys[k] = 
                keys[k] == 'desc' || keys[k] == -1  ? -1 
              : (keys[k] == 'skip' || keys[k] === 0 ? 0 
              : 1);
    }
    
    this.sort(function(a, b) {
        var sorted = 0, ix = 0;
    
        while (sorted === 0 && ix < KL) {
            var k = obIx(keys, ix);
            if (k) {
                var dir = keys[k];
                sorted = keySort(a[k], b[k], dir);
                ix++;
            }
        }
        return sorted;
    });
    return this;
    };
    

    sample usage:

    var obja = [
      {USER:"bob",  SCORE:2000, TIME:32,    AGE:16, COUNTRY:"US"},
      {USER:"jane", SCORE:4000, TIME:35,    AGE:16, COUNTRY:"DE"},
      {USER:"tim",  SCORE:1000, TIME:30,    AGE:17, COUNTRY:"UK"},
      {USER:"mary", SCORE:1500, TIME:31,    AGE:19, COUNTRY:"PL"},
      {USER:"joe",  SCORE:2500, TIME:33,    AGE:18, COUNTRY:"US"},
      {USER:"sally",    SCORE:2000, TIME:30,    AGE:16, COUNTRY:"CA"},
      {USER:"yuri", SCORE:3000, TIME:34,    AGE:19, COUNTRY:"RU"},
      {USER:"anita",    SCORE:2500, TIME:32,    AGE:17, COUNTRY:"LV"},
      {USER:"mark", SCORE:2000, TIME:30,    AGE:18, COUNTRY:"DE"},
      {USER:"amy",  SCORE:1500, TIME:29,    AGE:19, COUNTRY:"UK"}
    ];
    
    var sorto = {
      SCORE:"desc",TIME:"asc", AGE:"asc"
    };
    
    obja.keySort(sorto);
    

    yields the following:

     0: {     USER: jane;     SCORE: 4000;    TIME: 35;       AGE: 16;    COUNTRY: DE;   }
     1: {     USER: yuri;     SCORE: 3000;    TIME: 34;       AGE: 19;    COUNTRY: RU;   }
     2: {     USER: anita;    SCORE: 2500;    TIME: 32;       AGE: 17;    COUNTRY: LV;   }
     3: {     USER: joe;      SCORE: 2500;    TIME: 33;       AGE: 18;    COUNTRY: US;   }
     4: {     USER: sally;    SCORE: 2000;    TIME: 30;       AGE: 16;    COUNTRY: CA;   }
     5: {     USER: mark;     SCORE: 2000;    TIME: 30;       AGE: 18;    COUNTRY: DE;   }
     6: {     USER: bob;      SCORE: 2000;    TIME: 32;       AGE: 16;    COUNTRY: US;   }
     7: {     USER: amy;      SCORE: 1500;    TIME: 29;       AGE: 19;    COUNTRY: UK;   }
     8: {     USER: mary;     SCORE: 1500;    TIME: 31;       AGE: 19;    COUNTRY: PL;   }
     9: {     USER: tim;      SCORE: 1000;    TIME: 30;       AGE: 17;    COUNTRY: UK;   }
     keySort: {  }
    

    (using a print function from here)

    here is a jsbin example.

    edit: cleaned up and posted as mksort.js on github.

    0 讨论(0)
  • 2020-11-22 13:53

    String Appending Method

    You can sort by multiple values simply by appending the values into a string and comparing the strings. It is helpful to add a split key character to prevent runoff from one key to the next.

    Example

    const arr = [ 
        { a: 1, b: 'a', c: 3 },
        { a: 2, b: 'a', c: 5 },
        { a: 1, b: 'b', c: 4 },
        { a: 2, b: 'a', c: 4 }
    ]
    
    
    function sortBy (arr, keys, splitKeyChar='~') {
        return arr.sort((i1,i2) => {
            const sortStr1 = keys.reduce((str, key) => str + splitKeyChar+i1[key], '')
            const sortStr2 = keys.reduce((str, key) => str + splitKeyChar+i2[key], '')
            return sortStr1.localeCompare(sortStr2)
        })
    }
    
    console.log(sortBy(arr, ['a', 'b', 'c']))

    0 讨论(0)
  • 2020-11-22 13:54

    You could concat the 2 variables together into a sortkey and use that for your comparison.

    list.sort(function(a,b){
       var aCat = a.var1 + a.var2;
       var bCat = b.var1 + b.var2;
       return (aCat > bCat ? 1 : aCat < bCat ? -1 : 0);
    });
    
    0 讨论(0)
  • 2020-11-22 13:56

    I have just published to npm a micro-library called sort-helper (source on github). The idea is to import the helper by to create the comparison function for sort array method through the syntax items.sort(by(column, ...otherColumns)), with several way to express the columns to sort by:

    • By key: persons.sort(by('lastName', 'firstName')),
    • By selector: dates.sort(by(x => x.toISOString())),
    • In descending order: [3, 2, 4, 1].sort(by(desc(n => n)))[3, 2, 1, 0],
    • Ignoring case: ['B', 'D', 'c', 'a'].sort(by(ignoreCase(x => x))).join('')'aBcD'.

    It's similar to the nice thenBy mentioned in this answer but with the following differences that may be more to the taste of some:

    • An approach more functional than object-oriented (see thenBy fluent API),
    • A syntax a bit terser and still as much readable, natural almost like SQL.
    • Fully implemented in TypeScript, to benefit from type safety and type expressivity.
    0 讨论(0)
提交回复
热议问题