我正在尝试按属性对对象数组进行排序。我跑:
array.sort(function(a, b){
var textA = a.name.toUpperCase();
var textB = b.name.toUpperCase();
return (textA < textB) ? -1 : (textA > textB) ? 1: 0
});
首先按字母顺序对数组对象进行排序,然后使用自定义比较函数运行array.sort,如下所示:
array.sort(function(a, b){
if(a.name === b.name){
return -1;
}
return 1;
});
它似乎可以处理任何没有重复的对象,但是,只要有双打它就会将它们全部推送到数组的末尾,而不仅仅是附加内容。
示例:
[
{name: 'Amy'},
{name: 'Amy'},
{name: 'Clark'},
{name: 'Clark'},
{name: 'Dan'},
{name: 'Dave'}
{name: 'Joe'},
{name: 'Joe'}
]
预期产出:
实际结果:
排序代码尝试获得预期结果
array.sort(function(a,b){
if(a.name === b.name){return -1}
return 1;
});
我有一种感觉,带有比较功能的array.sort可以处理这个但是我一直在玩返回值0,-1,1并且似乎无法让它完全按照我的意愿运行。
更新
预期成果标准:
如果对象具有相同的名称,则副本应该到达数组的末尾。例如,如果有两个Amy&#39;一个停留在数组的开头,副本就到了最后。因此,所有第一次出现的名称都将在数组的开头,并且每次在数组末尾都将重新排序所有双精度数,三重等。因此,它可能会安排alhpabetical多项。
示例:
[
{name: 'Amy'},
{name: 'Amy'},
{name: 'Clark'},
{name: 'Clark'},
{name: 'Clark'},
{name: 'Dan'},
{name: 'Dave'},
{name: 'Joe'},
{name: 'Joe'},
{name: 'Joe'},
]
预期结果:
艾米 克拉克 担 戴夫 乔 艾米 - 重复 克拉克 - 重复 乔 - 重复 克拉克 - 有三分之一 乔 - 有第三个
正如您所看到的,它按字母顺序排列所有名称的首次出现。然后按字母顺序排序第二次,然后排第三次。直到所有重复项都得到解决。
在评论中谈到后,我的理解是它不能单独在array.sort函数中完成。单独使用比较函数排序似乎对单个或分组双精度有好处,但不适用于在数组末尾放置双精度数。
答案 0 :(得分:5)
您的比较器功能不正确。该功能必须:
因为你的不一致,排序过程会混淆。对于您的情况,最简单的方法是.localeCompare()
函数,它会返回您需要的结果:
array.sort(function(a, b) { return a.name.localeCompare(b.name); });
根据您的“预期输出”,您的订购标准尚不清楚。在任何情况下,排序比较器,无论它做什么,都必须是一致的:当两个项以任意顺序传递给它时,函数应该报告相同的顺序。
编辑如果原始排序具有某种语义含义,并且“双打”(我称之为“重复”)应该在数组中进一步向下排序,您可以为每个排序添加另一个属性捕获原始状态的对象:
var keyMap = {};
array.forEach(function(item) {
if (item.name in keyMap)
item.position = ++keyMap[item.name];
else
keyMap[item.name] = item.position = 1;
});
现在您可以排序:
array.sort(function(a, b) {
var c = a.position - b.position;
if (c) return c;
return a.name.localeCompare(b.name);
});
如果“position”值相同,则将按名称对项目进行排序。在原始数组中重复的项目将在非项目之后进行排序(并且三重之后的项目将按照这些项目排序等)。
答案 1 :(得分:4)
您可以通过使用具有相同组数组的哈希表的临时对象来使用sorting with map。从中获取已使用数组的长度作为排序组。
使用组和索引进行排序。
结果与已排序的临时数组的索引相映射。
Tge第一部分生成一个数组,其中包含原始数组的索引及其从将值推入同一组中的组。实际上我们在推动组后需要oly数组长度。如果更多项目位于同一组中,则这些项目将在稍后进行排序。
[ { index: 0, // Amy group: 1 }, { index: 1, // Amy group: 2 }, { index: 2, // Dan group: 1 }, { index: 3, // Joe group: 1 }, { index: 4, // Joe group: 2 } ]
然后上面给出的数组按组和索引进行排序,两者都是升序。
在最后一部分,将使用已排序数组的索引值映射新数组。
var array = [{ name: 'Amy' }, { name: 'Amy' }, { name: 'Dan' }, { name: 'Joe' }, { name: 'Joe' }],
groups = Object.create(null),
result = array
// this part is only necessary if the names should be in ascending order
// for keeping the given order, remove the part until next comment
.sort(function (a, b) {
return a.name.localeCompare(b.name);
})
// remove until here, if necessary
.map(function (a, i) {
return { index: i, group: (groups[a.name] = groups[a.name] || []).push(0) };
})
.sort(function (a, b) {
return a.group - b.group || a.index - b.index;
})
.map(function (o) {
return array[o.index];
});
console.log(result);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
未分类数据的示例。
var array = [{ name: 'Joe', i: 0 }, { name: 'Dan', i: 1 }, { name: 'Amy', i: 2 }, { name: 'Joe', i: 3 }, { name: 'Amy', i: 4 }],
groups = Object.create(null),
result = array
.map(function (a, i) {
return {
index: i,
group: (groups[a.name] = groups[a.name] || []).push(0),
value: a.name
};
})
.sort(function (a, b) {
return a.group - b.group || a.value.localeCompare(b.value);
})
.map(function (o) {
return array[o.index];
});
console.log(result);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
答案 2 :(得分:0)
您可以先加入重复项并计算其出现次数:
const array = [
{name: 'Amy'},
{name: 'Amy'},
{name: 'Dan'},
{name: 'Joe'},
{name: 'Joe'}
];
const counted = [], byName = {};
for(var {name} of array){
if(byName[name]){
byName[name].count++;
}else{
counted.push(byName[name] = {name, count:1});
}
}
现在名称是唯一的,我们可以按字母顺序排序:
counted.sort((a, b) => a.name.localeCompare(b.name));
最后,我们需要再次传播名称:
const result = [];
while(counted.length){
for(var i = 0; i < counted.length; i++){
const name = counted[i];
result.push(name.name);
name.count--;
if(!name.count){
counted.splice(i, 1);
i--;
}
}
}
答案 3 :(得分:0)
function compareSimple(a, b) {
if (a > b) {
return 1;
} else if (a < b) {
return -1;
}
return 0;
}
function compareAlphabetic(a, b) {
return compareSimple(a.name.toUpperCase(), b.name.toUpperCase());
}
let input = [
{ name: 'Amy' },
{ name: 'Amy' },
{ name: 'Clark' },
{ name: 'Clark' },
{ name: 'Dan' },
{ name: 'Clark' },
{ name: 'Dave' },
{ name: 'Joe' },
{ name: 'Joe' },
];
let output = input
.sort(compareAlphabetic)
.reduce(function(acc, curr) {
let rank = 0
let prev = acc.length > 0 ? acc[acc.length-1] : null
if (prev && compareAlphabetic(prev.value, curr) === 0) {
rank = prev.rank + 1
}
acc.push({ value: curr, rank: rank });
return acc
}, [])
// now we have an array like this
// [
// { value: Amy, rank: 0},
// { value: Amy, rank: 1},
// { value: Clark, rank: 0},
// ...]
// Now let's sort it by rank AND name
.sort(function(a, b) {
let result = compareSimple(a.rank, b.rank);
if (result !== 0) {
return result;
}
return compareAlphabetic(a.value, b.value);
})
// we have to unpack it all back:
.map(function(obj) {
return obj.value;
});
console.log(output);
// [ { name: 'Amy' },
// { name: 'Clark' },
// { name: 'Dan' },
// { name: 'Dave' },
// { name: 'Joe' },
// { name: 'Amy' },
// { name: 'Clark' },
// { name: 'Joe' },
// { name: 'Clark' } ]
答案 4 :(得分:0)
派对有点晚了,但这绝对应该这样做:
var arr = [
{name: 'Amy'},
{name: 'Amy'},
{name: 'Clark'},
{name: 'Clark'},
{name: 'Clark'},
{name: 'Dan'},
{name: 'Dave'},
{name: 'Joe'},
{name: 'Joe'},
{name: 'Joe'},
{name: 'Joe'},
{name: 'Joe'}
];
const o = arr.reduce(
(acc,item)=>{
(acc[item.name]===undefined)
? acc[item.name]=1
: acc[item.name]+=1
return acc;
}
,{}
);
const highest = Object.keys(o).reduce(
(acc,item)=>
(o[item]>acc)
? o[item]
: acc
,1
);
const sort = (all,level=1,results=[]) => {
const dub = [""," - Duplicate"," - Had a third"," - Had a fourth"];
if(level>highest){
return results;
}
results = results.concat(
all.filter(
item=>
//if you don't want Clark and Joe to show up 3 times:
// level===1
// ? level<=o[item]
// : level===o[item]
level<=o[item]
)
.filter((item,index,all)=>all.indexOf(item)===index)
.sort()
.map(x=>
x+
(dub[level-1]===undefined
? " - more than four"
: dub[level-1]
)
)
);
return sort(all,level+1,results)
}
console.log(
sort(
arr.map(x=>x.name)
)
);