有效地对字典(或 JS 中的任何键值数据结构)进行排序word_number键

sort a dictionary (or whatever key-value data structure in js) on word_number keys efficiently

本文关键字:排序 word number 数据结构 键值 字典 JS 任何 有效地      更新时间:2023-09-26

如何按键对字典进行排序,例如

dict["word_21"] = "Hello Java";
dict["word_22"] = "Hello World";
dict["word_11"] = "Hello Javascript";

这样我就得到了

dict["word_22"] = "Hello World";
dict["word_21"] = "Hello Java";
dict["word_11"] = "Hello Javascript";

仅在索引上有word_number组合,并且值是字符串。索引是不同的(没有相等的值),但在错误情况下可能是"未定义的"

编辑:实际上我需要它的降序和升序。但降序是我目前需要的。

javascript对象,这里用作键值映射(称为"字典"),没有顺序;即你不能排序。

为此,您需要一个数组,例如

[
    {id: "word_11", entry:"Hello Javascript"},
    {id: "word_21", entry:"Hello Java"},
    {id: "word_22", entry:"Hello World"},
]

然后,您可以按ID或条目对其进行排序。你可以使用你的id-sort-algorithms。


或者,您可以使用未排序的数据结构旁边的键数组进行排序。这可能是最好(高效)和最简单的方法:

var dict = {
    "word_21": "Hello Java",
    "word_22": "Hello World",
    "word_11": "Hello Javascript"
}; // init (like your example)
var keys = Object.keys(dict); // or loop over the object to get the array
// keys will be in any order
keys.sort(); // maybe use custom sort, to change direction use .reverse()
// keys now will be in wanted order
for (var i=0; i<keys.length; i++) { // now lets iterate in sort order
    var key = keys[i];
    var value = dict[key];
    /* do something with key & value here */
} 

试试这个

var sorted = [];
for(var key in dict) {
    sorted[sorted.length] = key;
}
sorted.sort();

dict键进行排序并将其写回对象对我来说没有意义,但在这里:

function sortOnKeys(dict) {
    var sorted = [];
    for(var key in dict) {
        sorted[sorted.length] = key;
    }
    sorted.sort();
    var tempDict = {};
    for(var i = 0; i < sorted.length; i++) {
        tempDict[sorted[i]] = dict[sorted[i]];
    }
    return tempDict;
}
dict = sortOnKeys(dict);

如果你只想对对象中的键进行排序,下面就可以了(它是一行)

/**
 * (typescript) returns the given object with keys sorted alphanumerically.
 * @param {T} obj the object to sort
 * @returns {T} the sorted object
 */
 const sort = <T extends object>(obj: T): T => Object.keys(obj).sort()
        .reduce((acc, c) => { acc[c] = obj[c]; return acc }, {}) as T

或在 JavaScript 中相同

/**
 * (javascript) returns the given object with keys sorted alphanumerically.
 * @param {T} obj the object to sort
 * @returns {T} the sorted object
 */
 const sort = (obj) => Object.keys(obj).sort()
        .reduce((acc, c) => { acc[c] = obj[c]; return acc }, {})

@Amberlamps不错的解决方案在大多数情况下都有效。但是,OP 是正确的,某些键存在拆分问题。在 javascript 中,sort() 的默认行为是使用字符串 Unicode 代码点来确定元素的顺序。例如,以下键将无法使用 @Amberlamps 方法正确排序:

canvas_2_1/15/2018__2:55:20_PM
canvas_24_1/15/2018__2:55:20_PM

但是我们可以利用 sort() 接受可选参数的事实来自定义排序方法,该参数是一个比较数组 2 个元素的函数

通过自定义比较函数的排序逻辑并将其传递给 sort() 方法,上面的键可以正确排序:

sorted.sort(function(a, b) {
    a = parseInt(get_between(a, 'canvas_', '_'));
    b = parseInt(get_between(b, 'canvas_', '_'));
    if (a > b) {
        return 1;
    }
    if (b > a) {
        return -1;
    }
    return 0;
    });

在这种情况下,我使用以下get_between方法:

function get_between(str, char_a, char_b) {
   res = str.split(char_a).pop().split(char_b).shift();
   return(res)
}

要点是,如果您有棘手的键(可能是也可能不是"正确"使用字典),您可以调整排序功能以仍然正确排序。

简单地说,字典类型没有 keys() 方法,而 Object 类型有。你可以向 Object.keys() 方法传递一个可迭代对象,并将键作为具有 .sort() 方法的列表返回。

Object.keys({r:2,d:2,c:3,p:0})
// returns ["r", "d", "c", "p"]
Object.keys({r:2,d:2,c:3,p:0}).sort()
// returns ["c", "d", "p", "r"]
Object.keys([6,7,8,9])
// returns ["0", "1", "2", "3"]

最后,让我们jsFiddleOP的代码。

更新:Bergi的答案太多了,我完全错过了"好答案"部分。我什至没有注意到他做了和我在jsFiddle中做过的同样的事情。

要理解为什么无法对字典进行排序,我们首先需要了解字典是如何工作的。与根据索引对其项目进行排序的列表不同,字典将项目存储在由其键的哈希指示的位置。使用您的示例,值"Hello Java"存储在"word_21"中。此过程涉及使用数学函数将"word_21"转换为可用作地址的数字。使用哈希表(字典的另一个名称)的好处是,它对于查找值非常有效,因为哈希键比搜索列表的每个元素要容易得多。

回顾一下,没有办法像您要求的那样重新排序字典。将一个值放在另一个值之前的唯一方法,即更改它的位置,是更改它的键。最好将顺序视为任意且不可预测的。

虽然字典对于基于键快速访问值非常有用,但您可以考虑根据您的情况使用不同的数据类型。当您可以更轻松地使用列表的索引时,为什么要使用编号键?如果您正在寻找一种基于键访问动态更改值的快速方法,请使用字典。如果要基于索引和排序快速访问元素,请使用列表。虽然,现在您可以找到大多数语言的有序词典,这些词典也将键存储在有序列表中以进行索引。在JS中,我相信这仍然需要第三方库。

在试图记住我的 JavaScript 语法时遇到了这个问题。这就是我解决它的方式,也许它会帮助某人。

// Unsorted Dictionary
YourDict = {
"A" : "1"
"C" : "3"
"B" : "2"
};
// The object sorting function
let alphabetizeByKey = function (dict) {
   // Init your return object
   let retObj = {};
   // Pull keys into array and use builtin array sort to alphabetize
   let keys = Object.keys(dict).sort();
   // If you want descending add keys.reverse();
   // Now loop through your new alphabetical key array
   // Creating a new entry in your return object (dictionary)
   // And add the value from original dict based on the key
   keys.forEach(k => {
      retObj[k] = dict[k];
   });
   return retObj;
}
// You can pass it in and set it to the sorted value returned from the function
YourDict = alphabetizeByKey(YourDict)

这是有效的,因为...

"可变值是可以在不创建全新值的情况下进行更改的值。 In JavaScript, objects and arrays are mutable by default,但基元值不是——一旦创建了基元值,就无法更改它,尽管持有它的变量可能会被重新分配。-MDN