Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 按属性按重要性顺序对JSON对象数组进行排序_Javascript_Arrays_Json_Sorting - Fatal编程技术网

Javascript 按属性按重要性顺序对JSON对象数组进行排序

Javascript 按属性按重要性顺序对JSON对象数组进行排序,javascript,arrays,json,sorting,Javascript,Arrays,Json,Sorting,我有一堆歌曲存储在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

我有一堆歌曲存储在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  }
];
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', '-']])
library.sort(priority(['album', '-year', '+title']));
or
library.sort(priority('album', '-year', '+title'));
我需要按字母和数字顺序按属性排序。有很多关于StackOverflow的文章和问题涉及到按单个值排序,有些文章和问题似乎涉及多个值,但它们没有顺序或重要性

我需要按几个值对每个对象(歌曲)进行排序,其中每个值的重要性级别较低。例如:

专辑
名称(字母)>
磁盘
编号(数字)>
曲目
编号(数字)>
标题
(字母)>等

这意味着相册是按字母顺序排列的。在每个唱片集中都有按唱片编号排序的歌曲,因此磁盘1中的所有歌曲都在顶部,然后磁盘2中的所有歌曲,等等。在每个唱片编号分组中,都是按曲目编号排序的歌曲。如果有多首歌曲具有相同的曲目编号,或者没有曲目编号,则将按歌曲标题按字母顺序进行排序。如果曲目标题也相同,则可以提供更多属性

大写不重要,它应该像正常的字母排序那样排序(如果它以数字开头,则在字母之前,特殊字符将像在传统排序中一样有它们的位置)

我尝试过使用这段代码(它有硬编码的排序值,并且没有磁盘号),但它只是按照代码中最内部的属性,track number进行排序

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

单个值也应该能够按降序排序,可能看起来像
-album
[“album”,true]
。语法是灵活的。

您可以使用如下函数:

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  }
];
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', '-']])
library.sort(priority(['album', '-year', '+title']));
or
library.sort(priority('album', '-year', '+title'));
这将按相册升序、磁盘升序、标题降序对库进行排序

正式用法:

opt:包含以下内容的数组:

  • 字符串(按升序对键“string”排序)

  • 排列
    • 0:字符串(对键“字符串”进行排序)
    • 1:“-”或“+”表示升序或降序(默认为升序)
我没有按照您所说的方式实现它,因为它会使以
-
开头的键无法按升序排序

编辑:

替代版本,与
'-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;
    };
}

您可以使用如下函数:

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  }
];
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', '-']])
library.sort(priority(['album', '-year', '+title']));
or
library.sort(priority('album', '-year', '+title'));
这将按相册升序、磁盘升序、标题降序对库进行排序

正式用法:

opt:包含以下内容的数组:

  • 字符串(按升序对键“string”排序)

  • 排列
    • 0:字符串(对键“字符串”进行排序)
    • 1:“-”或“+”表示升序或降序(默认为升序)
我没有按照您所说的方式实现它,因为它会使以
-
开头的键无法按升序排序

编辑:

替代版本,与
'-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;
    };
}

给你。。解决这个问题的一种方法是:

// 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));
//这有点老套,但很管用
//“a”表示按字母顺序进行比较
//“n”表示进行数字比较。
var sortKeys=[“唱片”、“a”、“磁盘”、“n”、“曲目”、“n”、“标题”、“n”];
按键功能(ao、bo){
var l=sortKeys.length;
var i=0;
var sortResult;
//仔细检查钥匙
而(ib.toLowerCase()){
返回+1;
}
如果(a.toLowerCase()==b.toLowerCase()){
//好的,这些字段匹配。重新启动循环
//因此,它将在中尝试下一个排序条件。
持续
}
扔(“不应该真的到这里。”);
}
如果(sortType==“n”){
//廉价的数字比较
返回+a-+b;
}
}
//所有字段的总匹配
返回0;
}
library.sort(按键);
log(JSON.stringify(library,null,2));

给你。。解决这个问题的一种方法是:

// 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));
//这有点老套,但很管用
//“a”表示按字母顺序进行比较
//“n”表示进行数字比较。
var sortKeys=[“唱片”、“a”、“磁盘”、“n”、“曲目”、“n”、“标题”、“n”];
按键功能(ao、bo){
var l=sortKeys.length;
var i=0;
var sortResult;
//仔细检查钥匙
而(ib.toLowerCase()){
返回+1;
}
如果(a.toLowerCase()==b.toLowerCase()){
//好的,这些字段匹配。重新启动循环
//因此,它将在中尝试下一个排序条件。
持续
}
扔(“不应该真的到这里。”);
}
如果(sortType==“n”){
//廉价的数字比较
返回+a-+