Sort array items and preserve order of same elements
假设我有这个数组:
1 2 3 4 5 6 | 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)" } ]; |
此函数用于按名称对数组进行排序:
1 2 3 4 5 | array.sort(function(a, b) { if (a.name < b.name) return -1; if (a.name > b.name) return 1; return 0; }); |
号
以及ECMAScript语言规范,它们告诉我:
The sort is not necessarily stable (that is, elements that compare
equal do not necessarily remain in their original order).
号
因此,排序后,名称=背景色的两个项目可能以任何顺序出现,即:
1 2 3 4 5 | [ { name:"background-color", value:"rgb(0, 0, 0)" }, { name:"background-color", value:"rgba(0, 0, 0, .5)" }, ... ] |
或
1 2 3 4 5 | [ { name:"background-color", value:"rgba(0, 0, 0, .5)" }, { name:"background-color", value:"rgb(0, 0, 0)" }, ... ] |
。
如何对数组进行排序,以便具有相同名称的项保持其相对顺序?我不想硬编码任何东西。
理论上,在排序之前,您可以跟踪数组中的索引,并在排序时将其考虑在内。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 }); |
因为数组包含引用类型objet,所以可以在sort函数中确定元素的索引。所以我们在排序前后都避免使用地图。
1 2 3 4 5 | 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)); |
。
向数组添加额外属性:order
1 2 3 4 5 6 | 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 } ]; |
号
如果名称相等,则将排序函数更改为按顺序排序:
1 2 3 4 5 6 7 | 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; } }); |
请注意,订单返回的符号必须根据您希望它的排序是递增还是递减进行调整(这里,我假设您是从最大到最小排序,所以返回具有较小顺序的排序)。