使用对象数组,如:
const data = [
{count: 400, value: "Car Wash Drops"},
{count: 48, value: "Personal/Seeding"},
{count: 48, value: "Personal/Seeding"},
];
我要map
到一个数组,该数组具有用于重复值的附加标识符:
const expected = [
["Car Wash Drops", 400],
["Personal/Seeding (1)", 48],
["Personal/Seeding (2)", 48],
];
到目前为止,我有一个映射函数来映射相应的值,但是不确定如何继续仅对重复项附加标识符。
data.map(d => [`${d.value}`, d.count]);
导致:
[
["Car Wash Drops", 400],
["Personal/Seeding", 48],
["Personal/Seeding", 48],
]
我也利用了索引,但是它在每个值上添加了索引:
data.map((d, i) => [`${d.value} ${i}`, d.count]);
导致:
[
["Car Wash Drops (0)", 400],
["Personal/Seeding (1)", 48],
["Personal/Seeding (2)", 48],
]
答案 0 :(得分:3)
使用您的方法,您可以在地图内使用filter()
来检查原始数组中有多少元素具有与当前分析的元素相同的值,使用此条件,您可以选择要返回的值作为新值:
const data = [
{count: 400, value: "Car Wash Drops"},
{count: 48, value: "Personal/Seeding"},
{count: 48, value: "Personal/Seeding"},
];
let res = data.map((x, idx) =>
{
if (data.filter(y => y.value === x.value).length > 1)
return [`${x.value} (${idx})`, x.count];
else
return [`${x.value}`, x.count];
});
console.log(res);
如果我们使用some()
而不是filter()
,则可以改善前一种方法的性能,如下所示:
const data = [
{count: 400, value: "Car Wash Drops"},
{count: 48, value: "Personal/Seeding"},
{count: 48, value: "Personal/Seeding"},
{count: 300, value: "Operators/Management"},
{count: 48, value: "Personal/Seeding"}
];
let res = data.map((x, idx) =>
{
if (data.some((y, j) => y.value === x.value && idx !== j))
return [`${x.value} (${idx})`, x.count];
else
return [`${x.value}`, x.count];
});
console.log(res);
如果我们以前用元素在原始数组中出现的次数来创建Map,则可以做得更好。像这样:
const data = [
{count: 400, value: "Car Wash Drops"},
{count: 48, value: "Personal/Seeding"},
{count: 48, value: "Personal/Seeding"},
{count: 300, value: "Operators/Management"},
{count: 48, value: "Personal/Seeding"}
];
let counters = data.reduce((res, {value}) =>
{
res.set(value, res.has(value) ? res.get(value) + 1 : 1);
return res;
}, new Map());
let res = data.map((x, idx) =>
{
return [
`${x.value}` + (counters.get(x.value) > 1 ? `(${idx})` : ""),
x.count
];
});
console.log(res);
答案 1 :(得分:3)
已经给出了答案,在充分尊重答案作者的情况下,我认为可能在语法和性能上都可以对答案进行一些改进:
reduce
,但是如果源相对较小(data.length <1000),我总是更喜欢reduce
。尝试使用 POF(原为:)),因为它是最快的选择。
当我们处理 key-value 对时,ES6 Map是一个很好的助手,但是我更喜欢 POO(普通旧对象:))可能,它将使我们的代码更美观。
我将提供问题的解决方案(在最坏的情况下,它将运行O(n)并为键值对使用额外的O(n)空间,它在源代码上进行了两次遍历,因此,第二遍遍需要将1放在我们第一次遇到的地方时错过的地方:
let data = [
{count: 400, value: "Car Wash Drops"},
{count: 48, value: "Personal/Seeding"},
{count: 48, value: "Personal/Seeding"},
{count: 300, value: "Operators/Management"},
{count: 48, value: "Personal/Seeding"}
];
const map = {};
for (let i=0;i<data.length;i+=1) {
map[ data[i].value ] = map[ data[i].value ]+1 || 0;
data[i].value = map[data[i].value]?data[i].value+` (${map[data[i].value]+1})`:data[i].value;
}
for (let i=0;i<data.length;i+=1) {
data[i].value = map[data[i].value]?data[i].value+` (1)`:data[i].value;
}
console.log(data.map(o=>[o.value,o.count]));
使用ES6 of
运算符[link to of]或更简洁的版本:
let data = [
{count: 400, value: "Car Wash Drops"},
{count: 48, value: "Personal/Seeding"},
{count: 48, value: "Personal/Seeding"},
{count: 300, value: "Operators/Management"},
{count: 48, value: "Personal/Seeding"}
];
const map = {};
for (let d of data) {
map[d.value] = map[d.value]+1 || 0;
d.value = map[d.value]?d.value+` (${map[d.value]+1})`:d.value;
}
for (let d of data) {
d.value = map[d.value]?d.value+` (1)`:d.value;
}
console.log(data.map(o=>[o.value,o.count]));
答案 2 :(得分:0)
您可以维护从看到的值到看到的值之间的映射。然后,根据是否重复,更容易获得正确的号码:
const data = [
{count: 400, value: "Car Wash Drops"},
{count: 48, value: "Personal/Seeding"},
{count: 48, value: "Personal/Seeding"},
];
let valueCounts = data.reduce((a, c) => {
a[c.value] = a[c.value] || {current: 1, total: 0};
a[c.value].total += 1;
return a;
}, {});
const expected = data.map(({count, value}) => {
if (valueCounts[value].total === 1) return [value, count];
return [`${value} (${valueCounts[value].current++})`, count];
});
console.log(expected);
答案 3 :(得分:-1)
您可以在回调之后将第二个参数传递给.map()
。调用回调时,该值将用作this
的值。因此,您可以穿过一个对象,该对象可用于累积重复次数:
data.map(function(d, i) {
if (!(d.value in this))
this[d.value] = 0;
else
this[d.value] += 1;
return [
d.value + (this[d.value] ? " (" + this[d.value] + ")" : ""),
d.count
];
}, {});
通过从一个空对象开始,回调可以跟踪每个d.value
字符串被看到多少次。看到重复时,可以将限定符添加到字符串中。
现在,这并不能完全符合您的要求,因为它一次只能查看一个值。因此,它第一次看到"Personal/Seeding"
时就不知道它是重复项,因此不会被限定符修改。当然是第二次。
如果这还不够好,请执行您要求的操作,首先需要对数组进行完整遍历,以获得每个字符串的重复项最终计数。