我有一堆歌曲存储在一个JavaScript对象数组中。它看起来像这样:
var library = [
{ "title": "40 Years Later", "album": "Tears of Steel", "year": 2012, "track": 1, "disk": 1, "time": 31 },
{ "title": "The Dome", "album": "Tears of Steel", "year": 2012, "track": 2, "disk": 1, "time": 311 },
{ "title": "The Battle", "album": "Tears of Steel", "year": 2012, "track": 3, "disk": 1, "time": 123 },
{ "title": "End Credits", "album": "Tears of Steel", "year": 2012, "track": 4, "disk": 1, "time": 103 },
{ "title": "The Wires", "album": "Elephants Dream", "year": 2006, "track": 1, "disk": 1, "time": 75 },
{ "title": "Typewriter Dance", "album": "Elephants Dream", "year": 2006, "track": 2, "disk": 1, "time": 70 },
{ "title": "The Safest Place", "album": "Elephants Dream", "year": 2006, "track": 3, "disk": 1, "time": 45 },
{ "title": "Emo Creates", "album": "Elephants Dream", "year": 2006, "track": 4, "disk": 1, "time": 60 },
{ "title": "End Title", "album": "Elephants Dream", "year": 2006, "track": 5, "disk": 1, "time": 91 },
{ "title": "Teaser Music", "album": "Elephants Dream", "year": 2006, "track": 6, "disk": 1, "time": 75 },
{ "title": "Ambience", "album": "Elephants Dream", "year": 2006, "track": 7, "disk": 1, "time": 110 },
{ "title": "Snow Fight", "album": "Sintel", "year": 2010, "track": 1, "disk": 1, "time": 107 },
{ "title": "Finding Scales / Chicken Run", "album": "Sintel", "year": 2010, "track": 2, "disk": 1, "time": 107 },
{ "title": "The Ziggurat", "album": "Sintel", "year": 2010, "track": 3, "disk": 1, "time": 78 },
{ "title": "Expedition", "album": "Sintel", "year": 2010, "track": 4, "disk": 1, "time": 93 },
{ "title": "Dragon Blood Tree", "album": "Sintel", "year": 2010, "track": 5, "disk": 1, "time": 47 },
{ "title": "Cave Fight / Lament", "album": "Sintel", "year": 2010, "track": 6, "disk": 1, "time": 145 },
{ "title": "I Move On (Sintel's Song)", "album": "Sintel", "year": 2010, "track": 7, "disk": 1, "time": 169 },
{ "title": "Circling Dragons", "album": "Sintel", "year": 2010, "track": 8, "disk": 1, "time": 28 },
{ "title": "Trailer Music", "album": "Sintel", "year": 2010, "track": 9, "disk": 1, "time": 44 }
];
我需要按字母和数字顺序按属性排序。 StackOverflow上有很多关于按单个值排序的文章和问题,有些文章和问题似乎涵盖了多个值,但它们没有顺序或重要性。
我需要按几个值对每个对象(歌曲)进行排序,其中每个值的重要性等级较低。例如:
album
名称(按字母顺序排列)>disk
号(数字)>track
号(数字)>title
(按字母顺序排列)>等
这意味着相册在一起,每张专辑按字母顺序排列。在每张专辑中都有按磁盘编号排序的歌曲,因此磁盘1中的所有歌曲都在顶部,然后是磁盘2中的所有歌曲等。在每组磁盘编号中都是按曲目编号排序的歌曲。如果存在多首具有相同曲目编号的歌曲,或者不存在曲目编号,则将按字母顺序按歌曲标题对其进行排序。如果曲目标题也相同,则可以给出更多属性。
大写不应该重要,它应该像普通的字母排序那样排序(如果它以数字开头,那将在字母之前,特殊字符就像传统的排序一样)。
我尝试过使用此代码(它具有硬编码的排序值并且没有磁盘编号),但它只是 按代码中最内层属性排序,轨道号。
library.sort(function (a, b) {
if (a.album === b.album) {
if (a.track === b.track) {
var x = a.title.toLowerCase();
var y = b.title.toLowerCase();
return x < y ? -1 : x > y ? 1 : 0;
}
var x = a.track;
var y = b.track;
return x < y ? -1 : x > y ? 1 : 0;
}
return a.album.toLowerCase() - b.album.toLowerCase();
});
我正在寻找一个重新排列library
数组的函数,以便按照以下输入的方式对其进行排序:
sort(library, [ "album", "disk", "track", "title" ]);
个别值也应该能够按降序排序,可能看起来像-album
或["album", true]
。语法很灵活。
答案 0 :(得分:3)
您可以使用Alasql JavaScript SQL库对对象数组进行排序。它支持以任何顺序(如SQL)对许多字段进行排序。
对于许多种类,Alasql可能比其他排序函数更快,因为它将查询编译为JavaScript并将这些编译的查询函数保存到缓存中。
var res = alasql('SELECT *, LCASE(album) AS lalbum, LCASE(title) as ltitle FROM ? \
ORDER BY lalbum DESC, disk, ltrack, ltitle',[library]);
这里我以不区分大小写的方式为排序文本创建了两个附加字段(lalbum和ltitle)。
请与您的数据at jsFiddle
一起试用此示例答案 1 :(得分:2)
你可以使用这样的函数:
function priority(opt) {
if (!(opt instanceof Array)) {
opt = Array.prototype.slice.call(arguments);
}
return function (a, b) {
for (var i = 0; i < opt.length; ++i) {
var option = opt[i];
if (typeof option === 'string') {
option = [option, '+'];
}
if (option.length < 2) {
option[1] = '+';
}
if (a[option[0]] !== b[option[0]]) {
if (a[option[0]] === undefined) return 1;
if (b[option[0]] === undefined) return -1;
if (typeof a[option[0]] === 'string' || typeof b[option[0]] === 'string') {
return (option[1] === '+' ? String(a[option[0]]).toLowerCase() < String(b[option[0]]).toLowerCase() : String(a[option[0]]).toLowerCase() > String(b[option[0]]).toLowerCase()) ? -1 : 1;
} else {
return (option[1] === '+' ? a[option[0]] < b[option[0]] : a[option[0]] > b[option[0]]) ? -1 : 1;
}
}
}
return 0;
};
}
它的工作原理如下:
library.sort(priority(['album', 'disk', ['title', '-']])
这将按照专辑升序排序库,然后按磁盘升序排序,然后按标题降序排序
正式使用:
opt:包含以下内容的数组:
或
我没有按照你所说的方式实现它,因为它会使以-
开头的键无法按升序排序。
编辑:
备用版本,适用于'-album'
语法:
function priority(opt) {
if (!(opt instanceof Array)) {
opt = Array.prototype.slice.call(arguments);
}
return function (a, b) {
for (var i = 0; i < opt.length; ++i) {
var order = opt[i].substr(0, 1),
key = opt[i].substr(1);
if (order !== '-' && order !== '+') {
key = opt[i];
order = '+';
}
if (a[key] !== b[key]) {
if (a[key] === undefined) return 1;
if (b[key] === undefined) return -1;
if (typeof a[key] === 'string' || typeof b[key] === 'string') {
return (order === '+' ? String(a[key]).toLowerCase() < String(b[key]).toLowerCase() : String(a[key]).toLowerCase() > String(b[key]).toLowerCase()) ? -1 : 1;
} else {
return (order === '+' ? a[key] < b[key] : a[key] > b[key]) ? -1 : 1;
}
}
}
return 0;
};
}
这样使用:
library.sort(priority(['album', '-year', '+title']));
or
library.sort(priority('album', '-year', '+title'));
答案 2 :(得分:1)
在这里,您可以找到解决问题的方法:
// This is kinda hacky, but it works
// "a" means do an alphabetical compare
// "n" means do a numeric compare.
var sortKeys = ["album", "a", "disk", "n", "track", "n", "title", "n"];
function byKey(ao, bo) {
var l = sortKeys.length;
var i = 0;
var sortResult;
// Walk through the keys
while (i < l) {
// Get the field name
var field = sortKeys[i];
// Get the compare type
var sortType = sortKeys[i + 1];
// Get the values and force to string values
var a = "" + ao[field];
var b = "" + bo[field];
console.log([field, sortType]);
// Advance by two because we consume two array elements
i += 2;
// Our alphabletical compare
if (sortType === "a") {
if (a.toLowerCase() < b.toLowerCase()) {
return -1;
}
if (a.toLowerCase() > b.toLowerCase()) {
return +1;
}
if (a.toLowerCase() === b.toLowerCase()) {
// Ok, these fields match. Restart the loop
// So it will try the next sort criteria in.
continue;
}
throw ("Should never actually get here.");
}
if (sortType === "n") {
// Cheap numeric compare
return +a - +b;
}
}
// A total match across all fields
return 0;
}
library.sort(byKey);
console.log(JSON.stringify(library, null, 2));