JavaScript 自然排序对象

3

I have an object array like

array[0] = {id: 1, name: "First"}
array[1] = {id: 2, name: "Second"}

我曾尝试通过使用名称字段进行排序,但是未成功:

Array.prototype.alphanumSort = function (caseInsensitive) {
for (var z = 0, t; t = ((typeof this[z] == "string" || typeof this[z] == "undefined") ? this[z] : this[z].name); z++) {
    this[z] = new Array();
    var x = 0, y = -1, n = 0, i, j;

    while (i = (j = t.charAt(x++)).charCodeAt(0)) {
        var m = (i == 46 || (i >= 48 && i <= 57));
        if (m !== n) {
            this[z][++y] = "";
            n = m;
        }
        this[z][y] += j;
    }
}

this.sort(function (a, b) {
    for (var x = 0, aa, bb; (aa = a[x]) && (bb = b[x]); x++) {
        if (caseInsensitive) {
            aa = aa.toLowerCase();
            bb = bb.toLowerCase();
        }
        if (aa !== bb) {
            var c = Number(aa), d = Number(bb);
            if (c == aa && d == bb) {
                return c - d;
            } else return (aa > bb) ? 1 : -1;
        }
    }
    return a.length - b.length;
});

for (var z = 0; z < this.length; z++)
    this[z] = this[z].join("");
}

但我从中得到的列表只包含一个数组,其中只有name字段,没有对应的id。为什么会这样呢? 是否有一种方法可以将此算法应用于过滤对象? 我是JavaScript新手,请多多包涵。


2
你看过String#localeCompare和其中的选项吗? - Nina Scholz
请不要将方法放在原型链上。 - Ayush Gupta
没问题 @AyushGupta - OP从来没有真正使用过那段代码。 - Jaromanda X
@NinaScholz 如果我有像“Ex 10”和“Ex 2”这样的情况怎么办?第二个应该是第一个。 - LAffair
3个回答

5
你可以使用 排序与映射,以及带有 optionsString#localeCompare

sensitivity

字符串中哪些差异应导致非零结果值。可能的值包括:

  • "base":仅有基本字母不同的字符串被视为不相等。例如:a ≠ ba = áa = A
  • "accent":仅有基本字母、重音和其他变音符号不同的字符串被视为不相等。例如:a ≠ ba ≠ áa = A
  • "case":仅有基本字母或大小写不同的字符串被视为不相等。例如:a ≠ ba = áa ≠ A
  • "variant":在基本字母、重音和其他变音符号或大小写不同的字符串被视为不相等的情况下,还会考虑其他差异。例如:a ≠ ba ≠ áa ≠ A

对于使用 "sort" 的情况,默认值为 "variant";对于使用 "search" 的情况,则取决于区域设置。

numeric

是否应使用数字排序,使得 "1" < "2" < "10"。可能的值为 truefalse;默认值为 false。可以通过选项属性或 Unicode 扩展键来设置此选项;如果两者都提供,则以 options 属性为准。实现不需要支持此属性。

var array = ['Ex 10', 'Ex 2', 'a 10.1', 'a 1.1', 'a 10.0', 'a 2.0'];

array.sort((a, b) => a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' }));

console.log(array)


2
你可以使用 String.prototype.localeCompare。

var arr = [
  {id: 1, name: "Third"},
  {id: 2, name: "Fifth"},
  {id: 3, name: "Second"},
  {id: 4, name: "Fourth"},
  {id: 5, name: "First"}
];

arr.sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }));

console.log(arr);


在像“First 10”和“First 2”这样排序名称的情况下,第二个应该排在第一位。 - LAffair
1
如果某个对象中没有name属性,你的代码将会用字符串“undefined”来与其他字符串进行比较。 - barbsan
在这种情况下,我建议编写一个自定义函数来比较两个字符串,该函数将返回1、-1和0到Array.sort(),就像vizsatiz所建议的那样。如果我有一些空闲时间,我会尝试去做,并更新我的答案。 - PR7
1
@PR7 不需要自定义函数,请参见其他答案 - barbsan
@Dana 抱歉,我很忙,忘记正确更新代码了。现在我已经纠正了它。 - PR7
显示剩余2条评论

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接