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 对数组项进行排序并保留相同元素的顺序_Javascript_Arrays_Sorting - Fatal编程技术网

Javascript 对数组项进行排序并保留相同元素的顺序

Javascript 对数组项进行排序并保留相同元素的顺序,javascript,arrays,sorting,Javascript,Arrays,Sorting,假设我有这个数组: var array = [ { name: "border-color", value: "#CCCCCC" }, { name: "color", value: "#FFFFFF" }, { name: "background-color", value: "rgb(0, 0, 0)" }, { name: "background-color", value: "rgba(0, 0, 0, .5)" } ]; 此函数用于按名称对数组进行排序: array.

假设我有这个数组:

var array = [
  { name: "border-color", value: "#CCCCCC" },
  { name: "color", value: "#FFFFFF" },
  { name: "background-color", value: "rgb(0, 0, 0)" },
  { name: "background-color", value: "rgba(0, 0, 0, .5)" }
];
此函数用于按名称对数组进行排序:

array.sort(function(a, b) {
  if (a.name < b.name) return -1;
  if (a.name > b.name) return 1;
  return 0;
});


如何对数组进行排序,使同名项保持其相对顺序?我不想硬编码任何东西。

理论上,在排序之前,您可以跟踪其在数组中的索引,并在排序时将其考虑在内

var sortArray = yourarray.map(function(data, idx){
    return {idx:idx, data:data}
})

sortArray.sort(function(a, b) {
  if (a.data.name < b.data.name) return -1;
  if (a.data.name > b.data.name) return 1;
  return a.idx - b.idx
});

var answer = sortArray.map(function(val){
    return val.data
});
var sortArray=yourarray.map(函数(数据,idx){
返回{idx:idx,data:data}
})
sortArray.sort(函数(a,b){
if(a.data.nameb.data.name)返回1;
返回a.idx-b.idx
});
var answer=sortArray.map(函数(val){
返回val.data
});

向数组添加一个额外属性:order

var array = [
    { name: "border-color", value: "#CCCCCC", order: 1 },
    { name: "color", value: "#FFFFFF", order: 2 },
    { name: "background-color", value: "rgb(0, 0, 0)", order: 3 },
    { name: "background-color", value: "rgba(0, 0, 0, .5)", order: 4 }
];
然后,如果名称相等,则将“排序”函数更改为“按顺序排序”:

array.sort(function(a, b) {
    if (a.name < b.name) return -1;
    if (a.name > b.name) return 1;
    if (a.name == b.name) {
        if(a.order > b.order) return -1; else return 1;
    }
});
array.sort(函数(a,b){
如果(a.nameb.name)返回1;
如果(a.name==b.name){
如果(a.订单>b.订单)返回-1;否则返回1;
}
});

请注意,订单的返回符号必须根据您希望其排序是递增还是递减进行调整(这里,我假设您是从最大到最小排序,因此返回顺序较小的一个)。

因为数组包含引用类型objet,元素的索引可以在sort函数中确定。因此,我们避免在排序之前和之后使用映射

sortArray.sort((function(a, b) {
  if (a.name < b.name) return -1;
  if (a.name > b.name) return 1;
  return this.indexOf(a) - this.indexOf(b);
}).bind(sortArray));
sortArray.sort((函数a,b){
如果(a.nameb.name)返回1;
返回此.indexOf(a)-此.indexOf(b);
}).bind(sortArray));
这一点最近有所改变<代码>数组#排序稳定,这意味着具有相同<代码>名称的两个条目之间的相对位置将与排序数组之前相同:

22.1.3.27Array.prototype.sort(比较)

此数组的元素已排序排序必须稳定(即,比较相等的元素必须保持其原始顺序)

(我的重点)

因此,在您的例子中,
{name:“background color”,value:“rgb(0,0,0)”}
{name:“background color”,value:“rgba(0,0,0,5)”}
的顺序将保持不变,因为它们的比较结果相同


在ES2019之前,排序不需要是稳定的,因此它们可以颠倒顺序-或者不颠倒顺序,这取决于实现。

在ES6中,如果由于浏览器环境或transpiler插件设置而无法保证排序顺序(在理想情况下,这不应该是问题),非常惯用/快速的方法可以是:

values
 .map((v, i) => ([v,i]))
 .sort(([v1,i1], [v2,i2])=> (
     (v1==v2) ? (i2-i1) : (v2-v1)
)).map(([v,i])=>v); // or above flipped
这种方法的缺点是它不如合并排序有效,但它非常接近,因为大多数浏览器实现都将其用于
Array.prototype.sort
内部或甚至更优化(在这种情况下,应该是O(2n)+O(nlogn))


优点是它非常方便且易于阅读——在返回语句之后,不需要使用
else
。如果(a.order>b.order)返回-1,您只需执行
;返回1。您还可以删除包装
if(a.name==b.name){}
语句,该语句在执行时始终为true(因为它既不是
也不是
你从哪里得到
idx
的?很好,修复了映射上参数的名称function@noveyak由于数组包含引用类型objet,元素的索引可以在排序函数中确定。因此,我们避免在排序之前和之后使用映射。这不是很慢,因为它s每次都要找到索引吗?抱歉投了反对票:这不好,因为this.indexOf(a)和this.indexOf(b)排序时会发生变化。排序前需要记住初始索引使用@IONESHO添加,当数组中有多个值相同的项时,indexOf函数也会返回错误的索引。有关稳定排序的简短ES6实现,请查看此答案:
sortArray.sort((function(a, b) {
  if (a.name < b.name) return -1;
  if (a.name > b.name) return 1;
  return this.indexOf(a) - this.indexOf(b);
}).bind(sortArray));
values
 .map((v, i) => ([v,i]))
 .sort(([v1,i1], [v2,i2])=> (
     (v1==v2) ? (i2-i1) : (v2-v1)
)).map(([v,i])=>v); // or above flipped