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

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

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

我要做的是按 owner_namepublication_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_namepublication_name进行排序呢?

180459 次浏览

如果所有者名称不同,则按照它们进行排序。否则,使用出版物名称作为决胜局。

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

这对各种大小的 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);

遇到一个需要做 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 上

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

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

这里可以看到一个例子

您可以将这两个变量连接到一个 sortkey 中,并使用它进行比较。

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);
});
function multiSort() {


var args =$.makeArray( arguments ),
sortOrder=1, prop='', aa='',  b='';


return function (a, b) {


for (var i=0; i<args.length; i++){


if(args[i][0]==='-'){
prop=args[i].substr(1)
sortOrder=-1
}
else{sortOrder=1; prop=args[i]}


aa = a[prop].toLowerCase()
bb = b[prop].toLowerCase()


if (aa < bb) return -1 * sortOrder;
if (aa > bb) return 1 * sortOrder;


}


return 0
}


}
empArray.sort(multiSort( 'lastname','firstname')) Reverse with '-lastname'

我建议使用一个内置的比较器,并用逻辑或 ||链接所需的排序顺序。

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

实例:

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

我使用的是 ng-grid,需要对从 API 返回的记录数组进行多列排序,所以我提出了这个漂亮的动态多排序函数。

首先,ng-grid为“ ngGridSorted”触发一个“ event”,并将这个结构传回,描述排序:

sortData = {
columns:    DOM Element,
directions: [], //Array of string values desc or asc. Each index relating to the same index of fields
fields:     [], //Array of string values
};

因此,我构建了一个函数,它将根据上面所示的 sortData(不要被滚动条吓到!只有大约50行长!还有,我很抱歉弄脏了。它阻止了一个水平滚动条!)动态生成一个排序函数:

function SortingFunction(sortData)
{
this.sortData = sortData;


this.sort = function(a, b)
{
var retval = 0;


if(this.sortData.fields.length)
{
var i = 0;


/*
Determine if there is a column that both entities (a and b)
have that are not exactly equal. The first one that we find
will be the column we sort on. If a valid column is not
located, then we will return 0 (equal).
*/
while(  (   !a.hasOwnProperty(this.sortData.fields[i])
||  !b.hasOwnProperty(this.sortData.fields[i])
||  (a.hasOwnProperty(this.sortData.fields[i])
&& b.hasOwnProperty(this.sortData.fields[i])
&& a[this.sortData.fields[i]] === b[this.sortData.fields[i]])
) && i < this.sortData.fields.length){
i++;
}


if(i < this.sortData.fields.length)
{
/*
A valid column was located for both entities
in the SortData. Now perform the sort.
*/
if(this.sortData.directions
&& i < this.sortData.directions.length
&& this.sortData.directions[i] === 'desc')
{
if(a[this.sortData.fields[i]] > b[this.sortData.fields[i]])
retval = -1;
else if(a[this.sortData.fields[i]] < b[this.sortData.fields[i]])
retval = 1;
}
else
{
if(a[this.sortData.fields[i]] < b[this.sortData.fields[i]])
retval = -1;
else if(a[this.sortData.fields[i]] > b[this.sortData.fields[i]])
retval = 1;
}
}
}


return retval;
}.bind(this);
}

然后对 API (results)的结果进行排序,如下所示:

results.sort(new SortingFunction(sortData).sort);

我希望有人像我一样喜欢这个解决方案! 谢谢!

对许多字符串字段进行排序的一个好方法是使用 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 语句中链接起来。

我找到 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)
<script src="https://cdn.rawgit.com/peterkhayes/multisort/master/multisort.js"></script>

This library more mutch powerful, that was my case. Try it.

我在显示来自某些虚拟 DOMh- 函数组合的输出的内存池块时遇到了类似的问题。基本上,我面临着同样的问题,如排序多标准的数据,如从世界各地的球员的得分结果。

我注意到多准则排序是:

- sort by the first column
- if equal, sort by the second
- if equal, sort by the third
-  etc... nesting and nesting if-else

如果你不在乎,你可能很快就会失败,在一个如果-否则筑巢地狱... 像回拨地狱的承诺..。

如果我们写一个“谓词”函数来决定替代使用的哪一部分呢?这个谓语很简单:

// useful for chaining test
const decide = (test, other) => test === 0 ? other : test

现在,在编写了分类测试(byCountrySize,byAge,byGameType,byScore,byLevel...)之后,无论谁需要,你都可以加权你的测试(1 = asc,-1 = desc,0 = able) ,把它们放在一个数组中,然后应用一个简化的“ decision”函数,如下所示:

const multisort = (s1, s2) => {
const bcs = -1 * byCountrySize(s1, s2) // -1 = desc
const ba =  1 *byAge(s1, s2)
const bgt = 0 * byGameType(s1, s2) // 0 = doesn't matter
const bs = 1 * byScore(s1, s2)
const bl = -1 * byLevel(s1, s2) // -1 = desc


// ... other weights and criterias


// array order matters !
return [bcs, ba, bgt, bs, bl].reduce((acc, val) => decide(val, acc), 0)
}


// invoke [].sort with custom sort...
scores.sort(multisort)

瞧!这取决于你自己定义你的标准/重量/顺序... ... 但是你已经有了想法。希望这个能帮上忙!

编辑: * 确保每一栏有一个总排序次序 * 注意列顺序之间没有依赖关系,没有循环依赖关系

如果,不,排序可能是不稳定的!

试试这个:

t.sort( (a,b)=> a[3].localeCompare(b[3]) || a[1].localeCompare(b[1]) );

let t = [
//[publicationID, publication_name, ownderID, owner_name ]
[1, 'ZBC', 3, 'John Smith'],
[2, 'FBC', 5, 'Mike Tyson'],
[3, 'ABC', 7, 'Donald Duck'],
[4, 'DBC', 1, 'Michael Jackson'],
[5, 'XYZ', 2, 'Michael Jackson'],
[6, 'BBC', 4, 'Michael Jackson'],
];
  

// owner_name subarrray index = 3
// publication_name subarrray index = 1


t.sort( (a,b)=> a[3].localeCompare(b[3]) || a[1].localeCompare(b[1]) );


console.log(t.join('\n'));

我假设数组 let t = [ [publicationID, publication_name, ownderID, owner_name ], ... ]中的数据的索引为 owner _ name = 3和 publications _ name = 1。

我自己的用于处理 ES6迭代器 (blinq)的库允许(在其他事情中)简单的多级排序

const blinq = window.blinq.blinq
// or import { blinq } from 'blinq'
// or const { blinq } = require('blinq')
const dates = [{
day: 1, month: 10, year: 2000
},
{
day: 1, month: 1, year: 2000
},
{
day: 2, month: 1, year: 2000
},
{
day: 1, month: 1, year: 1999
},
{
day: 1, month: 1, year: 2000
}
]
const sortedDates = blinq(dates)
.orderBy(x => x.year)
.thenBy(x => x.month)
.thenBy(x => x.day);


console.log(sortedDates.toArray())
// or console.log([...sortedDates])
<script src="https://cdn.jsdelivr.net/npm/blinq@2.0.2"></script>

来源: < a href = “ https://GitHub.com/slawirszwan/javascript-multi-column-sort”rel = “ nofollow norefrer”> GitHub

function sortMethodAsc(a, b) {
return a == b ? 0 : a > b ? 1 : -1;
}


function sortMethodWithDirection(direction) {
if (direction === undefined || direction == "asc") {
return sortMethodAsc;
} else {
return function(a, b) {
return -sortMethodAsc(a, b);
}
}
}


function sortMethodWithDirectionByColumn(columnName, direction){
const sortMethod = sortMethodWithDirection(direction)
return function(a, b){
return sortMethod(a[columnName], b[columnName]);
}
}


function sortMethodWithDirectionMultiColumn(sortArray) {
//sample of sortArray
// sortArray = [
//     { column: "column5", direction: "asc" },
//     { column: "column3", direction: "desc" }
// ]
const sortMethodsForColumn = (sortArray || []).map( item => sortMethodWithDirectionByColumn(item.column, item.direction) );
return function(a,b) {
let sorted = 0;
let index = 0;
while (sorted === 0 && index < sortMethodsForColumn.length) {
sorted = sortMethodsForColumn[index++](a,b);
}
return sorted;
}
}


//=============================================
//=============================================
//=============================================
//test


var data = [
{"CountryName":"Aruba","CountryCode":"ABW","GNI":280},{
"CountryName":"Afghanistan","CountryCode":"ABW","GNI":280},{"CountryName":"Angola","CountryCode":"AGO","GNI":280},{"CountryName":"Albania","CountryCode":"ALB","GNI":4320},
{"CountryName":"Arab World","CountryCode":"ARB","GNI":280},{"CountryName":"United Arab Emirates","CountryCode":"ARE","GNI":39130},
{"CountryName":"Argentina","CountryCode":"ARG","GNI":13030},{"CountryName":"Armenia","CountryCode":"ARM","GNI":3990},{"CountryName":"American Samoa","CountryCode":"ASM","GNI":280},
{"CountryName":"Antigua and Barbuda","CountryCode":"ATG","GNI":13810},{"CountryName":"Australia","CountryCode":"AUS","GNI":51360},
{"CountryName":"Austria","CountryCode":"AUT","GNI":45440},{"CountryName":"Azerbaijan","CountryCode":"AZE","GNI":4080},{"CountryName":"Burundi","CountryCode":"BDI","GNI":280},
{"CountryName":"Belgium","CountryCode":"BEL","GNI":41790},{"CountryName":"Benin","CountryCode":"BEN","GNI":800},{"CountryName":"Burkina Faso","CountryCode":"BFA","GNI":590},
{"CountryName":"Bangladesh","CountryCode":"BGD","GNI":1470},{"CountryName":"Bulgaria","CountryCode":"BGR","GNI":7860},{"CountryName":"Bahrain","CountryCode":"BHR","GNI":21150},
{"CountryName":"Bosnia and Herzegovina","CountryCode":"BIH","GNI":4910},{"CountryName":"Belarus","CountryCode":"BLR","GNI":5280},
{"CountryName":"Belize","CountryCode":"BLZ","GNI":4390},{"CountryName":"Bolivia","CountryCode":"BOL","GNI":3130},{"CountryName":"Brazil","CountryCode":"BRA","GNI":8600},
{"CountryName":"Barbados","CountryCode":"BRB","GNI":15270},{"CountryName":"Brunei Darussalam","CountryCode":"BRN","GNI":29600},
{"CountryName":"Bhutan","CountryCode":"BTN","GNI":2660},{"CountryName":"Botswana","CountryCode":"BWA","GNI":6730},
{"CountryName":"Central African Republic","CountryCode":"CAF","GNI":390},{"CountryName":"Canada","CountryCode":"CAN","GNI":42870},
{"CountryName":"Central Europe and the Baltics","CountryCode":"CEB","GNI":13009},{"CountryName":"Switzerland","CountryCode":"CHE","GNI":80560},
{"CountryName":"Chile","CountryCode":"CHL","GNI":13610},{"CountryName":"China","CountryCode":"CHN","GNI":8690},{"CountryName":"Cote d'Ivoire","CountryCode":"CIV","GNI":1580},
{"CountryName":"Cameroon","CountryCode":"CMR","GNI":1370},{"CountryName":"Colombia","CountryCode":"COL","GNI":5890},{"CountryName":"Comoros","CountryCode":"COM","GNI":1280},
{"CountryName":"Cabo Verde","CountryCode":"CPV","GNI":3030},{"CountryName":"Costa Rica","CountryCode":"CRI","GNI":11120},
{"CountryName":"Caribbean small states","CountryCode":"CSS","GNI":8909},{"CountryName":"Cyprus","CountryCode":"CYP","GNI":23720},
{"CountryName":"Czech Republic","CountryCode":"CZE","GNI":18160},{"CountryName":"Germany","CountryCode":"DEU","GNI":43490},
{"CountryName":"Djibouti","CountryCode":"DJI","GNI":1880},{"CountryName":"Dominica","CountryCode":"DMA","GNI":6590},{"CountryName":"Denmark","CountryCode":"DNK","GNI":55220},
{"CountryName":"Dominican Republic","CountryCode":"DOM","GNI":6630},{"CountryName":"Algeria","CountryCode":"DZA","GNI":3940},
{"CountryName":"East Asia & Pacific (excluding high income)","CountryCode":"EAP","GNI":6987},{"CountryName":"Early-demographic dividend","CountryCode":"EAR","GNI":3352},
{"CountryName":"East Asia & Pacific","CountryCode":"EAS","GNI":10171},{"CountryName":"Europe & Central Asia (excluding high income)","CountryCode":"ECA","GNI":7375},
{"CountryName":"Europe & Central Asia","CountryCode":"ECS","GNI":22656},{"CountryName":"Ecuador","CountryCode":"ECU","GNI":5920},
{"CountryName":"Euro area","CountryCode":"EMU","GNI":35645},{"CountryName":"Spain","CountryCode":"ESP","GNI":27180},{"CountryName":"Estonia","CountryCode":"EST","GNI":18190},
{"CountryName":"Ethiopia","CountryCode":"ETH","GNI":740},{"CountryName":"European Union","CountryCode":"EUU","GNI":32784},
{"CountryName":"Fragile and conflict affected situations","CountryCode":"FCS","GNI":1510},{"CountryName":"Finland","CountryCode":"FIN","GNI":44580},
{"CountryName":"Fiji","CountryCode":"FJI","GNI":4970},{"CountryName":"France","CountryCode":"FRA","GNI":37970},{"CountryName":"Gabon","CountryCode":"GAB","GNI":6650},
{"CountryName":"United Kingdom","CountryCode":"GBR","GNI":40530},{"CountryName":"Georgia","CountryCode":"GEO","GNI":3780},{"CountryName":"Ghana","CountryCode":"GHA","GNI":1880},
{"CountryName":"Guinea","CountryCode":"GIN","GNI":790},{"CountryName":"Guinea-Bissau","CountryCode":"GNB","GNI":660},
{"CountryName":"Equatorial Guinea","CountryCode":"GNQ","GNI":7050},{"CountryName":"Greece","CountryCode":"GRC","GNI":18090},
{"CountryName":"Grenada","CountryCode":"GRD","GNI":9180},{"CountryName":"Guatemala","CountryCode":"GTM","GNI":4060},{"CountryName":"Guyana","CountryCode":"GUY","GNI":4500},
{"CountryName":"High income","CountryCode":"HIC","GNI":40142},{"CountryName":"Honduras","CountryCode":"HND","GNI":2250},{"CountryName":"Heavily indebted poor countries (HIPC)","CountryCode":"HPC","GNI":904},{"CountryName":"Croatia","CountryCode":"HRV","GNI":12570},{"CountryName":"Haiti","CountryCode":"HTI","GNI":760},{"CountryName":"Hungary","CountryCode":"HUN","GNI":12870},{"CountryName":"IBRD only","CountryCode":"IBD","GNI":5745},{"CountryName":"IDA & IBRD total","CountryCode":"IBT","GNI":4620},{"CountryName":"IDA total","CountryCode":"IDA","GNI":1313},{"CountryName":"IDA blend","CountryCode":"IDB","GNI":1791},
{"CountryName":"Indonesia","CountryCode":"IDN","GNI":3540},{"CountryName":"IDA only","CountryCode":"IDX","GNI":1074},{"CountryName":"India","CountryCode":"IND","GNI":1800},{"CountryName":"Ireland","CountryCode":"IRL","GNI":55290},{"CountryName":"Iraq","CountryCode":"IRQ","GNI":4630},{"CountryName":"Iceland","CountryCode":"ISL","GNI":60830},{"CountryName":"Israel","CountryCode":"ISR","GNI":37270},{"CountryName":"Italy","CountryCode":"ITA","GNI":31020},{"CountryName":"Jamaica","CountryCode":"JAM","GNI":4760},{"CountryName":"Jordan","CountryCode":"JOR","GNI":3980},{"CountryName":"Japan","CountryCode":"JPN","GNI":38550},{"CountryName":"Kazakhstan","CountryCode":"KAZ","GNI":7970},{"CountryName":"Kenya","CountryCode":"KEN","GNI":1460},{"CountryName":"Kyrgyz Republic","CountryCode":"KGZ","GNI":1130},
{"CountryName":"Cambodia","CountryCode":"KHM","GNI":1230},{"CountryName":"Kiribati","CountryCode":"KIR","GNI":3010},{"CountryName":"St. Kitts and Nevis","CountryCode":"KNA","GNI":16240},{"CountryName":"Kuwait","CountryCode":"KWT","GNI":31430},{"CountryName":"Latin America & Caribbean (excluding high income)","CountryCode":"LAC","GNI":7470},{"CountryName":"Lao PDR","CountryCode":"LAO","GNI":2270},{"CountryName":"Lebanon","CountryCode":"LBN","GNI":8400},{"CountryName":"Liberia","CountryCode":"LBR","GNI":620},{"CountryName":"Libya","CountryCode":"LBY","GNI":5500},{"CountryName":"St. Lucia","CountryCode":"LCA","GNI":8830},{"CountryName":"Latin America & Caribbean","CountryCode":"LCN","GNI":8251},{"CountryName":"Least developed countries: UN classification","CountryCode":"LDC","GNI":1011},{"CountryName":"Low income","CountryCode":"LIC","GNI":774},{"CountryName":"Sri Lanka","CountryCode":"LKA","GNI":3850},{"CountryName":"Lower middle income","CountryCode":"LMC","GNI":2118},{"CountryName":"Low & middle income","CountryCode":"LMY","GNI":4455},{"CountryName":"Lesotho","CountryCode":"LSO","GNI":1210},{"CountryName":"Late-demographic dividend","CountryCode":"LTE","GNI":8518},{"CountryName":"Lithuania","CountryCode":"LTU","GNI":15200},{"CountryName":"Luxembourg","CountryCode":"LUX","GNI":70260},{"CountryName":"Latvia","CountryCode":"LVA","GNI":14740},{"CountryName":"Morocco","CountryCode":"MAR","GNI":2860},{"CountryName":"Moldova","CountryCode":"MDA","GNI":2200},{"CountryName":"Madagascar","CountryCode":"MDG","GNI":400},{"CountryName":"Maldives","CountryCode":"MDV","GNI":9760},
{"CountryName":"Middle East & North Africa","CountryCode":"MEA","GNI":7236},{"CountryName":"Mexico","CountryCode":"MEX","GNI":8610},{"CountryName":"Marshall Islands","CountryCode":"MHL","GNI":4840},{"CountryName":"Middle income","CountryCode":"MIC","GNI":4942},{"CountryName":"Mali","CountryCode":"MLI","GNI":770},
{"CountryName":"Malta","CountryCode":"MLT","GNI":24080},{"CountryName":"Myanmar","CountryCode":"MMR","GNI":1210},{"CountryName":"Middle East & North Africa (excluding high income)","CountryCode":"MNA","GNI":3832},{"CountryName":"Montenegro","CountryCode":"MNE","GNI":7400},{"CountryName":"Mongolia","CountryCode":"MNG","GNI":3270},{"CountryName":"Mozambique","CountryCode":"MOZ","GNI":420},{"CountryName":"Mauritania","CountryCode":"MRT","GNI":1100},{"CountryName":"Mauritius","CountryCode":"MUS","GNI":10130},{"CountryName":"Malawi","CountryCode":"MWI","GNI":320},{"CountryName":"Malaysia","CountryCode":"MYS","GNI":9650},{"CountryName":"North America","CountryCode":"NAC","GNI":56721},{"CountryName":"Namibia","CountryCode":"NAM","GNI":4570},{"CountryName":"Niger","CountryCode":"NER","GNI":360},{"CountryName":"Nigeria","CountryCode":"NGA","GNI":2100},
{"CountryName":"Nicaragua","CountryCode":"NIC","GNI":2130},{"CountryName":"Netherlands","CountryCode":"NLD","GNI":46180},{"CountryName":"Norway","CountryCode":"NOR","GNI":75990},{"CountryName":"Nepal","CountryCode":"NPL","GNI":800},{"CountryName":"Nauru","CountryCode":"NRU","GNI":10220},{"CountryName":"New Zealand","CountryCode":"NZL","GNI":38970},{"CountryName":"OECD members","CountryCode":"OED","GNI":37273},{"CountryName":"Oman","CountryCode":"OMN","GNI":14440},{"CountryName":"Other small states","CountryCode":"OSS","GNI":12199},{"CountryName":"Pakistan","CountryCode":"PAK","GNI":1580},{"CountryName":"Panama","CountryCode":"PAN","GNI":13280},{"CountryName":"Peru","CountryCode":"PER","GNI":5960},{"CountryName":"Philippines","CountryCode":"PHL","GNI":3660},{"CountryName":"Palau","CountryCode":"PLW","GNI":12700},{"CountryName":"Papua New Guinea","CountryCode":"PNG","GNI":2340},{"CountryName":"Poland","CountryCode":"POL","GNI":12730},{"CountryName":"Pre-demographic dividend","CountryCode":"PRE","GNI":1379},{"CountryName":"Portugal","CountryCode":"PRT","GNI":19820},{"CountryName":"Paraguay","CountryCode":"PRY","GNI":5470},{"CountryName":"West Bank and Gaza","CountryCode":"PSE","GNI":3180},{"CountryName":"Pacific island small states","CountryCode":"PSS","GNI":3793},{"CountryName":"Post-demographic dividend","CountryCode":"PST","GNI":41609},{"CountryName":"Qatar","CountryCode":"QAT","GNI":60510},{"CountryName":"Romania","CountryCode":"ROU","GNI":10000},{"CountryName":"Russian Federation","CountryCode":"RUS","GNI":9230},{"CountryName":"Rwanda","CountryCode":"RWA","GNI":720},{"CountryName":"South Asia","CountryCode":"SAS","GNI":1729},{"CountryName":"Saudi Arabia","CountryCode":"SAU","GNI":20090},{"CountryName":"Sudan","CountryCode":"SDN","GNI":2380},{"CountryName":"Senegal","CountryCode":"SEN","GNI":1240},{"CountryName":"Singapore","CountryCode":"SGP","GNI":54530},{"CountryName":"Solomon Islands","CountryCode":"SLB","GNI":1920},{"CountryName":"Sierra Leone","CountryCode":"SLE","GNI":510},{"CountryName":"El Salvador","CountryCode":"SLV","GNI":3560},{"CountryName":"Serbia","CountryCode":"SRB","GNI":5180},{"CountryName":"Sub-Saharan Africa (excluding high income)","CountryCode":"SSA","GNI":1485},{"CountryName":"Sub-Saharan Africa","CountryCode":"SSF","GNI":1486},{"CountryName":"Small states","CountryCode":"SST","GNI":11099},{"CountryName":"Sao Tome and Principe","CountryCode":"STP","GNI":1770},{"CountryName":"Suriname","CountryCode":"SUR","GNI":5150},{"CountryName":"Slovak Republic","CountryCode":"SVK","GNI":16610},{"CountryName":"Slovenia","CountryCode":"SVN","GNI":22000},{"CountryName":"Sweden","CountryCode":"SWE","GNI":52590},{"CountryName":"Eswatini","CountryCode":"SWZ","GNI":2950},{"CountryName":"Seychelles","CountryCode":"SYC","GNI":14170},{"CountryName":"Chad","CountryCode":"TCD","GNI":640},{"CountryName":"East Asia & Pacific (IDA & IBRD countries)","CountryCode":"TEA","GNI":7061},
{"CountryName":"Europe & Central Asia (IDA & IBRD countries)","CountryCode":"TEC","GNI":7866},{"CountryName":"Togo","CountryCode":"TGO","GNI":610},{"CountryName":"Thailand","CountryCode":"THA","GNI":5950},{"CountryName":"Tajikistan","CountryCode":"TJK","GNI":990},{"CountryName":"Turkmenistan","CountryCode":"TKM","GNI":6380},{"CountryName":"Latin America & the Caribbean (IDA & IBRD countries)","CountryCode":"TLA","GNI":8179},{"CountryName":"Timor-Leste","CountryCode":"TLS","GNI":1790},{"CountryName":"Middle East & North Africa (IDA & IBRD countries)","CountryCode":"TMN","GNI":3839},{"CountryName":"Tonga","CountryCode":"TON","GNI":4010},{"CountryName":"South Asia (IDA & IBRD)","CountryCode":"TSA","GNI":1729},
{"CountryName":"Sub-Saharan Africa (IDA & IBRD countries)","CountryCode":"TSS","GNI":1486},{"CountryName":"Trinidad and Tobago","CountryCode":"TTO","GNI":15340},{"CountryName":"Tunisia","CountryCode":"TUN","GNI":3490},{"CountryName":"Turkey","CountryCode":"TUR","GNI":10940},{"CountryName":"Tuvalu","CountryCode":"TUV","GNI":4970},{"CountryName":"Tanzania","CountryCode":"TZA","GNI":910},{"CountryName":"Uganda","CountryCode":"UGA","GNI":600},{"CountryName":"Ukraine","CountryCode":"UKR","GNI":2390},{"CountryName":"Upper middle income","CountryCode":"UMC","GNI":8197},{"CountryName":"Uruguay","CountryCode":"URY","GNI":15250},{"CountryName":"United States","CountryCode":"USA","GNI":58270},{"CountryName":"Uzbekistan","CountryCode":"UZB","GNI":2000},{"CountryName":"St. Vincent and the Grenadines","CountryCode":"VCT","GNI":7390},{"CountryName":"Vietnam","CountryCode":"VNM","GNI":2160},{"CountryName":"Vanuatu","CountryCode":"VUT","GNI":2920},{"CountryName":"World","CountryCode":"WLD","GNI":10371},{"CountryName":"Samoa","CountryCode":"WSM","GNI":4090},{"CountryName":"Kosovo","CountryCode":"XKX","GNI":3900},
{"CountryName":"South Africa","CountryCode":"ZAF","GNI":5430},{"CountryName":"Zambia","CountryCode":"ZMB","GNI":1290},{"CountryName":"Zimbabwe","CountryCode":"ZWE","GNI":1170},
{"CountryName":"Zimbabwe","CountryCode":"ZWE","GNI":1171}];


const sortMethod = sortMethodWithDirectionMultiColumn(
[
{ column: "GNI", direction: "asc" },
{ column: "CountryCode", direction: "desc" }
]
);
let sortedData = data.sort(sortMethod);
    

    

console.log("sorted by: 1)column:GNI-asc, 2)column:CountryCode-desc")
console.table(sortedData);
console.log(sortedData);

字符串追加方法

您可以按多个值进行排序,只需将这些值附加到一个字符串中并比较这些字符串。增加一个分键字符有助于防止从一个键到下一个键的径流。

例子

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']))

递归法

您也可以使用递归来完成此操作。它比字符串追加方法稍微复杂一些,但是它允许您在键级别上执行 ASC 和 DESC。我在评论每个部分,因为它有点复杂。

有一些注释掉的测试用于显示和验证顺序和默认顺序混合的排序工作。

例子

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) {
return arr.sort(function sort (i1,i2, sKeys=keys) {
// Get order and key based on structure
const compareKey = (sKeys[0].key) ? sKeys[0].key : sKeys[0];
const order = sKeys[0].order || 'ASC'; // ASC || DESC
// Calculate compare value and modify based on order
let compareValue = i1[compareKey].toString().localeCompare(i2[compareKey].toString())
compareValue = (order.toUpperCase() === 'DESC') ? compareValue * -1 : compareValue
// See if the next key needs to be considered
const checkNextKey = compareValue === 0 && sKeys.length !== 1
// Return compare value
return (checkNextKey) ? sort(i1, i2, sKeys.slice(1)): compareValue;
})
}


// console.log(sortBy(arr, ['a', 'b', 'c']))
console.log(sortBy(arr, [{key:'a',order:'desc'}, 'b', 'c']))
// console.log(sortBy(arr, ['a', 'b', {key:'c',order:'desc'}]))
// console.log(sortBy(arr, ['a', {key:'b',order:'desc'}, 'c']))
// console.log(sortBy(arr, [{key:'a',order:'asc'}, {key:'b',order:'desc'}, {key:'c',order:'desc'}]))

我刚刚向 npm 发表了一个名为 分类助手(< a href = “ https://github.com/rdeneau/sort-helper”rel = “ nofollow noReferrer”> source on github )的微型图书馆。其思想是通过语法 items.sort(by(column, ...otherColumns))导入辅助器 by,以创建 sort数组方法的比较函数,并通过几种方式表示按以下方式进行排序的列:

  • 作者: 钥匙: persons.sort(by('lastName', 'firstName')),
  • 作者: 选择器: dates.sort(by(x => x.toISOString())),
  • 降序排列: [3, 2, 4, 1].sort(by(desc(n => n)))[3, 2, 1, 0]中,
  • 忽略病例 : ['B', 'D', 'c', 'a'].sort(by(ignoreCase(x => x))).join('')'aBcD'

它类似于 这个答案中提到的漂亮的 到时候,但是有以下不同之处,可能更符合一些人的口味:

  • 一种比面向对象的 (见 thenBy流畅 API)更实用的方法,
  • 语法有点简洁,但仍然具有同样多的可读性,几乎像 SQL 一样自然。
  • 在 TypeScript 中完全实现,以受益于类型安全性和类型表达能力。

我需要这个为一个小项目,我的工作,所以性能不是优先考虑。

我有两个数组,我想要排序的 main数组和排序 rules的数组。我在排序回调函数中循环那个 rules数组,并试图尽快退出那个循环。

我使用乘数,以便转换 -11取决于天气,我排序的属性在升序或降序。

let array = [
{fullName: 'Michael Schumacher', sport: 'Formula 1'},
{fullName: 'Michael Jordan', sport: 'Basketball'},
{fullName: 'Damon Hill', sport: 'Formula 1'},
{fullName: 'Kobe Bryant', sport: 'Basketball'},
{fullName: 'Lebron James', sport: 'Basketball'},
{fullName: 'Lewis Hamilton', sport: 'Formula 1'},
];


const sortArray = (array, options) => {
if (!Array.isArray(options)) {
options = [{ key: options, order: 'asc' }];
}


options.forEach(item => {
item.multiplier = item.order != 'desc' ? -1 : 1;
});


return array.sort((firstItem, secondItem) => {
for (item of options) {
const { key, multiplier } = item;


const firstValue = firstItem[key];
const secondValue = secondItem[key];


if (firstValue != secondValue) {
return multiplier * (firstValue < secondValue ? 1 : -1);
}
}
return 0;
});
}


console.log('Original array');
console.log([...array]);


sortArray(array, 'sport');
console.log('Sorted by sport only (ascending, implicit, keeping the same order of athletes)');
console.log([...array]);


sortArray(array, [{key: 'sport'}, {key: 'fullName', order: 'desc'}]);
console.log('Sorted by sport (ascending, implicit), and by fullName (descending)');
console.log(array);

为了简化理解

Sort 方法比较数字,如果低于0,它将数字排序到 let,如果高于0,它将数字排序到右边。

因此,要添加多级排序,请检查 match = = = 0,然后进一步对它进行排序。

请看下面的例子

['a/b/c', 'a long piece of text/b', 'apple/b'].sort((a, b) => {
const asc = a.split('/').length - b.split('/').length
return asc
})
// outputs ['a long piece of text/b', 'apple/b', 'a/b/c']

['a/b/c', 'a long piece of text/b', 'apple/b'].sort((a, b) => {
const asc = a.split('/').length - b.split('/').length
return asc === 0 ? a.length - b.length : asc
})


// outputs: 'apple/b', 'a long piece of text/b', 'a/b/c'

我看到了很多复杂的解决方案,所以我在这里粘贴我正在使用的:

assignedIssues.sort((a, b) => {
let order = sortByText(a.assignee?.username, b.assignee?.username)


if (order === 0) order = sort(a.labels, b.labels, statusLabels)
if (order === 0) order = sort(a.labels, b.labels, priorityLabels)
if (order === 0) order = sortByText(a.web_url, b.web_url)


return order
})

我认为这是更具可读性,让您实现任何自定义排序功能的每一个级别,没有调用所有不必要的。

假设您想按多个索引排序,并假设您不知道每个字段的类型(字符串、数字或空)。 您可以创建一个函数,根据需要使用任意多个索引进行排序。

const compareWithType = (a, b) => {
if (typeof a === 'string') return a.localeCompare(b);
if (typeof a === 'number') return a - b;
return (!!a) - (!!b);  // to sort non-string non-number falsy or null values, modify as you like.
}
const compareWithIndexes = (...indexes) => {
return (a, b) => {
for (let i in indexes) {
let diff = 0;
while (!diff) {
compareWithType(a[i], b[i]);
}
return diff;
}
}
}
[[1, 2, 3, 4, 5], [0, 2, 3, 4, 6]].sort(compareWithIndexes(2, 3, 4));
// compares (3 - 3) then (4 - 4) then (5 - 6)