如何在多列上对数组进行排序?

fla*_*404 107 javascript sorting algorithm

我有一个多维数组.主数组是一个数组

[publicationID][publication_name][ownderID][owner_name] 
Run Code Online (Sandbox Code Playgroud)

我所试图做的是排序数组owner_name,然后通过publication_name.我知道你有JavaScript Array.sort(),你可以在其中放置自定义函数,在我的情况下,我有:

function mysortfunction(a, b) {
    var x = a[3].toLowerCase();
    var y = b[3].toLowerCase();

    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}
Run Code Online (Sandbox Code Playgroud)

这是罚款,只是排序上的一列,即OWNER_NAME,但我怎么修改它进行排序owner_name,然后publication_name

dcp*_*dcp 153

如果所有者名称不同,请按其排序.否则,使用发布名称作为决胜局.

function mysortfunction(a, b) {

  var o1 = a[3].toLowerCase();
  var o2 = b[3].toLowerCase();

  var p1 = a[1].toLowerCase();
  var p2 = b[1].toLowerCase();

  if (o1 < o2) return -1;
  if (o1 > o2) return 1;
  if (p1 < p2) return -1;
  if (p1 > p2) return 1;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • @ user26409021 - mysortfunction函数中不需要循环,因为Array.sort将根据需要调用函数,直到Array正确排序.mysortfunction唯一负责的是确定参数a和b是否相等,a是否小于b,或a是否大于b.我们不需要循环来做出决定.希望有所帮助. (3认同)
  • @ user26409021 - 不,那不对.它最终会[[A,5],[A,10],[J,5],[J,15]].它首先按第一个属性排序,如果它们相同,则按第二个属性排序.所以在你的例子中,A会出现在J之前.在两个元素的A相同的情况下,它将使用第二个属性.所以对于[A,10],[A,5],5出现在10之前,所以最终得到[A,5],[A,10]用于排序.你可能缺少的是当你使用Array.sort直到排序完成时多次调用mysortfunction. (2认同)

Teu*_*n D 54

我想你正在寻找的是byBy.js:https://github.com/Teun/thenBy.js

它允许您使用标准的Array.sort,但具有firstBy().thenBy().thenBy()样式.

这里可以看到一个例子.

  • 绝对不是这样的.当你调用thenBy()时,它会构造一个封装前一个函数的新函数.在排序时,javascript不会严格"循环"这些项目,但它会_will_调用你多次传递它的函数.使用thenBy不会改变调用次数.有关性能方面的考虑,请阅读:https://github.com/Teun/thenBy.js#a-word-on-performance (4认同)
  • 我明白了,我错了,感谢您考虑性能。也许添加一个关于使用新函数创建闭包的内存注意事项的注释? (3认同)

小智 24

需要按键进行SQL风格的混合asc和desc对象数组排序.

kennebec上面的解决方案帮我解决了这个问题:

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;
};
Run Code Online (Sandbox Code Playgroud)

样品用量:

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);
Run Code Online (Sandbox Code Playgroud)

产生以下结果:

 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: {  }
Run Code Online (Sandbox Code Playgroud)

(使用此处的打印功能)

这是一个jsbin的例子.

编辑:清理并在github上发布为mksort.js.


tbr*_*yen 22

对字符串的许多字段进行排序的好方法是使用toLocaleCompare和布尔运算符||.

就像是:

// Sorting record releases by name and then by title.
releases.sort((oldRelease, newRelease) => {
  const compareName = oldRelease.name.localeCompare(newRelease.name);
  const compareTitle = oldRelease.title.localeCompare(newRelease.title);

  return compareName || compareTitle;
})
Run Code Online (Sandbox Code Playgroud)

如果你想对更多字段进行排序,你可以简单地将它们与更多布尔运算符的return语句链接起来.

  • @ekkis,1和-1都是"truthy",所以这是一个非常优雅的解决方案.我刚刚这样做了:`sortItems =(a,b)=>(a.distance - b.distance)|| (a.name - b.name);`它对我的不挑剔的需求来说就像一个魅力. (5认同)
  • 确实如此,这做的工作比必要的多,但我只会在关键领域进行更改。对于对标称数量的数据进行排序的代码,代码的清晰度胜过性能。 (3认同)

ken*_*bec 17

这对于所有尺寸的alpha种类都很方便.将要排序的索引依次作为参数传递给它.

Array.prototype.deepSortAlpha= function(){
    var itm, L=arguments.length, order=arguments;

    var alphaSort= function(a, b){
        a= a.toLowerCase();
        b= b.toLowerCase();
        if(a== b) return 0;
        return a> b? 1:-1;
    }
    if(!L) return this.sort(alphaSort);

    this.sort(function(a, b){
        var tem= 0,  indx=0;
        while(tem==0 && indx<L){
            itm=order[indx];
            tem= alphaSort(a[itm], b[itm]); 
            indx+=1;        
        }
        return tem;
    });
    return this;
}

var arr= [[ "Nilesh","Karmshil"], ["Pranjal","Deka"], ["Susants","Ghosh"],
["Shiv","Shankar"], ["Javid","Ghosh"], ["Shaher","Banu"], ["Javid","Rashid"]];

arr.deepSortAlpha(1,0);
Run Code Online (Sandbox Code Playgroud)


Nin*_*olz 10

我建议使用内置的比较器,并将所需的排序顺序与逻辑或||.

function customSort(a, b) {
    return a[3].localeCompare(b[3]) || a[1].localeCompare(b[1]);
}
Run Code Online (Sandbox Code Playgroud)

工作范例:

var array = [
    [0, 'Aluminium', 0, 'Francis'],
    [1, 'Argon', 1, 'Ada'],
    [2, 'Brom', 2, 'John'],
    [3, 'Cadmium', 3, 'Marie'],
    [4, 'Fluor', 3, 'Marie'],
    [5, 'Gold', 1, 'Ada'],
    [6, 'Kupfer', 4, 'Ines'],
    [7, 'Krypton', 4, 'Joe'],
    [8, 'Sauerstoff', 3, 'Marie'],
    [9, 'Zink', 5, 'Max']
];

array.sort(function (a, b) {
    return a[3].localeCompare(b[3]) || a[1].localeCompare(b[1]);
});

document.write('<pre>');
array.forEach(function (a) {
    document.write(JSON.stringify(a) + '<br>');
});
Run Code Online (Sandbox Code Playgroud)


Tma*_*mac 8

您可以将2个变量连接在一起作为排序键并将其用于比较.

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);
});
Run Code Online (Sandbox Code Playgroud)


MiF*_*MiF 6

我找到了multisotr。这是一个简单、功能强大且小型的多重排序库。我需要使用动态排序标准对对象数组进行排序:

const criteria = ['name', 'speciality']
const data = [
  { name: 'Mike', speciality: 'JS', age: 22 },
  { name: 'Tom', speciality: 'Java', age: 30 },
  { name: 'Mike', speciality: 'PHP', age: 40 },
  { name: 'Abby', speciality: 'Design', age: 20 },
]

const sorted = multisort(data, criteria)

console.log(sorted)
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdn.rawgit.com/peterkhayes/multisort/master/multisort.js"></script>
Run Code Online (Sandbox Code Playgroud)

这个库更强大,这就是我的情况。尝试一下。