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

IT技术 javascript algorithm sorting
2021-01-24 14:31:27

我有一个多维数组。主要数组是一个数组

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

我想要做的是对数组进行排序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));
}

这是刚刚排序的一列,即OWNER_NAME很好,但我怎样修改它进行排序owner_name,然后publication_name

6个回答

如果所有者名称不同,请按它们排序。否则,对决胜局使用出版物名称。

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;
}
@dcp 我不知道它是如何对第二个属性进行排序的。除非你循环它与所选列的数量一样多..我说得对吗?例如[[A, 10], [J, 15], [A, 5], [J, 5]] => [[A, 10], [A, 5], [J, 15], [J, 5]]
2021-03-20 14:31:27
@user26409021 - mysortfunction 函数中不需要循环,因为 Array.sort 将根据需要调用该函数,直到 Array 正确排序。mysortfunction 唯一负责的是确定参数 a 和 b 是否相等,a 是否小于 b,或者 a 是否大于 b。我们不需要循环来做出决定。希望有帮助。
2021-03-20 14:31:27
@John Odom - 是的,您只需根据需要添加额外的排序条件。例如,如果您想按姓名、年龄和薪水(按此顺序)排序,您可以先在姓名上添加条件(例如,if 语句),然后是年龄,然后是薪水。条件的顺序很重要,因为放置条件的顺序控制应用排序逻辑的顺序。
2021-03-20 14:31:27
@dcp 这可以扩展到 3 列以上吗?
2021-03-30 14:31:27
@ 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 会被多次调用,直到排序完成。
2021-04-09 14:31:27

我想你要找的是 thenBy.js:https : //github.com/Teun/thenBy.js

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

一个例子可以在这里看到

我明白了,我错了,感谢您考虑性能。也许添加一个关于使用新函数创建闭包的内存注意事项的注释?
2021-03-13 14:31:27
事实并非如此。当您调用 thenBy() 时,它会构造一个封装前一个函数的新函数。在排序时,javascript 不会严格地“循环”项目,但它多次调用您传递给它的函数。使用 thenBy 不会改变调用次数。对于一些性能考虑,请阅读:github.com/Teun/thenBy.js#a-word-on-performance
2021-03-18 14:31:27
小心大型数据集的性能。每次thenBy调用时,所有数组项都会再次循环。
2021-03-22 14:31:27
@Harry 如果您无法使用它,请发布您无法排序的示例问题,以便其他人也可以学习。很高兴帮助你。github.com/Teun/thenBy.js/issues
2021-03-27 14:31:27
那么如何将其用于多个动态呢?还是在 for 循环中?
2021-04-06 14:31:27

对许多字符串字段进行排序的一种好方法是使用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;
})

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

确实如此,这做的工作比必要的多,但我只会在关键领域进行更改。对于对标称数量的数据进行排序的代码,代码的清晰度胜过性能。
2021-03-12 14:31:27
@bstst 你的方式更好,因为(a.name - b.name)除非必要,否则它不会评估即使不需要,首先创建变量也会做额外的工作。
2021-03-13 14:31:27
@ekkis,1 和 -1 都是“真实的”,所以这是一个非常优雅的解决方案。我刚刚完成了这个: sortItems = (a, b) => (a.distance - b.distance) || (a.name - b.name); 它对我不挑剔的需求来说就像一个魅力。
2021-03-18 14:31:27
事实上,你可以用一个 .reduce()
2021-04-06 14:31:27
但是,.localCompare()返回 -1, 0, 1 所以我认为您的解决方案不会像 || 对布尔值有好处
2021-04-08 14:31:27

遇到需要按键进行 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;
};

示例用法:

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

产生以下结果:

 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: {  }

(使用这里的打印功能

这是一个 jsbin 示例

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

这对于所有大小的 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);
请问您是从哪里收集这些数据的 [[“Nilesh”,“Karmshil”]、[“Pranjal”、“Deka”]、[“Susants”、“Ghosh”]、[“Shiv”、“Shankar”] , ["Javid","Ghosh"], ["Shaher","Banu"], ["Javid","Rashid"]];
2021-04-08 14:31:27