我有一个这样的对象数组:
[
{
name: "aaa",
mainName: "bbb",
occurrences: 3,
collectTime: "15-OCT-2018 09:03:02",
status: "unfinished"
},
{
name: "aaa",
mainName: "bbb",
occurrences: 2,
collectTime: "14-OCT-2018 05:63:42",
status: "unfinished"
},
{
name: "aaa",
mainName: "bbb",
occurrences: 5,
collectTime: "15-OCT-2018 10:56:35",
status: "finished"
},
{
name: "ccc",
mainName: "ddd",
occurrences: 7,
collectTime: "11-OCT-2018 13:12:41",
status: "finished"
},
{
name: "ccc",
mainName: "ddd",
occurrences: 10,
collectTime: "15-OCT-2018 09:03:02",
status: "finished"
},
{
name: "ccc",
mainName: "ddd",
occurrences: 4,
collectTime: "15-OCT-2018 22:36:32",
status: "unfinished"
},
]
但是,我似乎无法获得如下所示的数组:
[
{
name: "aaa",
mainName: "bbb",
occurrences: 5, // highest occurrences value for the unique combination of name and mainName
collectTime: "15-OCT-2018 10:56:35", // collectTime corresponding to the highest occurrences
finished: 1, // count of the status
unfinished: 2 // count of the status
},
{
name: "ccc",
mainName: "ddd",
occurrences: 10, // highest occurrences value for the unique combination of name and mainName
collectTime: "15-OCT-2018 09:03:02", // collectTime corresponding to the highest occurrences
finished: 2, // count of the status
unfinished: 1 // count of the status
},
]
我无法弄清楚您是如何使用Array.prototype.reduce()来获得所需的。我已经取得了一些进展,但无法完全获得确切的结果。任何指导都将不胜感激,谢谢!
答案 0 :(得分:1)
很高兴向您展示您的努力,但是仍然可以为您提供一个可行的解决方案。希望这将为您的下一个项目提供有益的启发:
const arr = [
{
name: "aaa",
mainName: "bbb",
occurrences: 3,
collectTime: "15-OCT-2018 09:03:02",
status: "unfinished"
},
{
name: "aaa",
mainName: "bbb",
occurrences: 2,
collectTime: "14-OCT-2018 05:63:42",
status: "unfinished"
},
{
name: "aaa",
mainName: "bbb",
occurrences: 5,
collectTime: "15-OCT-2018 10:56:35",
status: "finished"
},
{
name: "ccc",
mainName: "ddd",
occurrences: 7,
collectTime: "11-OCT-2018 13:12:41",
status: "finished"
},
{
name: "ccc",
mainName: "ddd",
occurrences: 10,
collectTime: "15-OCT-2018 09:03:02",
status: "finished"
},
{
name: "ccc",
mainName: "ddd",
occurrences: 4,
collectTime: "15-OCT-2018 22:36:32",
status: "unfinished"
},
];
// Reduce the array
const res = arr.reduce((current, next) => {
// Check whether the next item exists in the accumulator (current).
const needle = current.find(i => i.name === next.name && i.mainName === next.mainName);
// If it does...
if (needle) {
// increase the existing occurrences.
needle.occurrences += +next.occurrences;
// increase the status counter according to the next status.
needle[next.status] += 1;
// replace the collectTime if needed.
needle.collectTime = next.occurrences > needle.highestOccurrences ? next.collectTime : needle.collectTime;
// Keep track of the highest occurrence found so far.
needle.highestOccurrences = next.occurrences > needle.highestOccurrences ? next.occurrences : needle.highestOccurrences;
}
// Otherwise..
else {
// Create a "finished" property, and set it to 0.
next.finished = 0;
// Create an "unfinished" property, and set it to 0.
next.unfinished = 0;
// Keep track of the highest occurrence for that item.
next.highestOccurrences = next.occurrences;
// Increase the status of that item accordingly.
next[next.status] += 1;
// Push this item to the accumulator.
current.push(next);
}
return current;
}, []).map(function(item){
// Once done, just remove the undesired / unneeded properties.. BEWARE: this is unnecessary.
delete item.highestOccurrences;
delete item.status;
return item;
});
console.log(res);
解释直接在代码中。
请注意,使用find
代替过滤器,并使用单个reduce调用,已经可以很好地处理性能。
答案 1 :(得分:1)
如果找不到一个具有相同名称的对象,或者可以根据需要更新值,则可以采用一个新对象来缩小数组。
var data = [{ name: "aaa", mainName: "bbb", occurrences: 3, collectTime: "15-OCT-2018 09:03:02", status: "unfinished" }, { name: "aaa", mainName: "bbb", occurrences: 2, collectTime: "14-OCT-2018 05:63:42", status: "unfinished" }, { name: "aaa", mainName: "bbb", occurrences: 5, collectTime: "15-OCT-2018 10:56:35", status: "finished" }, { name: "ccc", mainName: "ddd", occurrences: 7, collectTime: "11-OCT-2018 13:12:41", status: "finished" }, { name: "ccc", mainName: "ddd", occurrences: 10, collectTime: "15-OCT-2018 09:03:02", status: "finished" }, { name: "ccc", mainName: "ddd", occurrences: 4, collectTime: "15-OCT-2018 22:36:32", status: "unfinished" }],
result = data.reduce((r, { name, mainName, occurrences, collectTime, status }) => {
var temp = r.find((o) => o.name === name);
if (temp) {
if (occurrences > temp.occurrences) {
temp.occurrences = occurrences;
temp.collectTime = collectTime;
}
temp[status]++;
} else {
r.push({
name,
mainName,
occurrences,
collectTime,
finished: +(status === 'finished'),
unfinished: +(status === 'unfinished') });
}
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 2 :(得分:0)
filter
将使您检查输出集中是否已经存在name
和mainName
的组合。一旦确定了这一点,就可以在没有匹配该组合的情况下推入当前条目,或者根据出现次数是否更多来更新值。
var input = [
{
name: "aaa",
mainName: "bbb",
occurrences: 3,
collectTime: "15-OCT-2018 09:03:02",
status: "unfinished"
},
{
name: "aaa",
mainName: "bbb",
occurrences: 2,
collectTime: "14-OCT-2018 05:63:42",
status: "unfinished"
},
{
name: "aaa",
mainName: "bbb",
occurrences: 5,
collectTime: "15-OCT-2018 10:56:35",
status: "finished"
},
{
name: "ccc",
mainName: "ddd",
occurrences: 7,
collectTime: "11-OCT-2018 13:12:41",
status: "finished"
},
{
name: "ccc",
mainName: "ddd",
occurrences: 10,
collectTime: "15-OCT-2018 09:03:02",
status: "finished"
},
{
name: "ccc",
mainName: "ddd",
occurrences: 4,
collectTime: "15-OCT-2018 22:36:32",
status: "unfinished"
},
]
const output = input.reduce((arr, obj) => {
let existing = arr.filter(t => t.name == obj.name && t.mainName == obj.mainName)[0]
if(existing){
if(obj.occurrences > existing.occurrences) {
Object.assign(existing, obj)
}
if(existing[obj.status]) {
existing[obj.status] += 1
} else {
existing[obj.status] = 1
}
delete existing.status
} else {
obj[obj.status] = 1
delete obj.status
arr.push(obj)
}
return arr
}, [])
console.log(output)
答案 3 :(得分:0)
这是-正如您提到的-经典.reduce
问题,但是在这种情况下,您的备忘录将有两个实体。由于您需要跟踪许多不同的实体并进行汇总,因此建议将其保留为对象的对象(由于这样,访问对象会更快)。从计算的角度来看,使用对象对象比使用map
中的另一个find
或任何其他数组操作要便宜。
因此,您的memo
用于reduce可能看起来像这样:
{
'aaa': {
/* aaa content here */
},
'ccc': {
/* ccc content here */
}
}
然后,第二步,您可以标准化对象(将其转换为数组)。这样,您就不必每次都在reduce中迭代备忘录数组。
我将假设name
和mainName
总是以相同的方式出现。如果存在多个组合,则必须调整“摘要”键才能使其唯一(例如memo[`${element.name}_${element.mainName}`]
-为了清楚起见,我使用模板字符串);
1。遍历原始数组以减少“摘要”
const result = myArray.reduce((memo, element) => {
const uniqueKey = `${element[name]}_${element.mainName}`;
// Initialize new memo key, if not available yet
if (!memo[uniqueKey]) {
memo[uniqueKey] = {
name: element.name,
mainName: element.mainName,
collectTime: element.collectTime,
occurrences: element.occurences,
finished: element.status === 'finished' ? 1 : 0,
unfinished: element.status === 'unfinished' ? 1 : 0,
};
}
// I assume there are only 2 statuses here available
if (element.status === 'finished') {
memo[uniqueKey].finished = memo.finished + 1;
} else {
memo[uniqueKey].unfinished = memo.unfinished + 1;
}
// Increase occurences, if needed
if (memo[uniqueKey].occurences < element.occurences) {
memo[uniqueKey].occurences = element.occurences;
memo[uniqueKey].collectTime = element.collectTime;
}
}, {});
2。将备忘录转换为数组。请注意,备忘录很短,因此转换很便宜:
const newArray = Object.values(result);
答案 4 :(得分:0)
使用Object
键作为键,还原为name
,使用Object.values
检索Array
的结果值(对象)。 注意:摘录getValues
中的代码仅以实际的reducer代码开头。
const grouped = Object.values(
getValues().reduce( (collection, value) => {
const isFinished = value.status === "finished";
const current = collection[value.name];
if (!current) {
collection[value.name] = { ...value,
finished: +(isFinished),
unfinished: +(!isFinished) };
delete collection[value.name].status;
} else {
collection[value.name] = { ...current,
occurrences: Math.max(value.occurrences, current.occurrences),
collectTime: new Date(current.collectTime) < new Date(value.collectTime)
? value.collectTime
: current.collectTime ,
finished: +(isFinished) + current.finished,
unfinished: +(!isFinished) + current.unfinished };
}
return collection;
}, {} )
);
console.log(grouped);
function getValues() {
return [
{
name: "aaa",
mainName: "bbb",
occurrences: 3,
collectTime: "15-OCT-2018 09:03:02",
status: "unfinished"
},
{
name: "aaa",
mainName: "bbb",
occurrences: 2,
collectTime: "14-OCT-2018 05:63:42",
status: "unfinished"
},
{
name: "aaa",
mainName: "bbb",
occurrences: 5,
collectTime: "15-OCT-2018 10:56:35",
status: "finished"
},
{
name: "ccc",
mainName: "ddd",
occurrences: 7,
collectTime: "11-OCT-2018 13:12:41",
status: "finished"
},
{
name: "ccc",
mainName: "ddd",
occurrences: 10,
collectTime: "15-OCT-2018 09:03:02",
status: "finished"
},
{
name: "ccc",
mainName: "ddd",
occurrences: 4,
collectTime: "15-OCT-2018 22:36:32",
status: "unfinished"
},
];
}