admin管理员组文章数量:1406942
I have an array of objects in javascript that i want to reduce. See code below. message with 6 or more digits is verified, fewer is unverified. I group them by group.
const myArray = [
{ group: 'groupA', message: 'Text without a number', sl: '1A' },
{ group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
{ group: 'groupB', message: 'Text without a number', sl: '1A' },
{ group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
{ group: 'groupB', message: 'Text with a number WO5467829', sl: '1A' },
{ group: 'groupC', message: 'Text without a number', sl: '1B' },
{ group: 'groupD', message: 'Text with a number Tick0127866', sl: '1B' },
{ group: 'groupC', message: 'Text without a number', sl: '1A' }
];
output = myArray.reduce((acc, line) => {
let yes = 0;
let no = 0;
line.message.match(/\d{6,}/) ? yes++ : no++;
acc[line.group] = acc[line.group] || {};
acc[line.group].verified = (acc[line.group].verified || 0) + yes;
acc[line.group].unverified = (acc[line.group].unverified || 0) + no;
return acc;
}, {});
console.log('output', output);
I have an array of objects in javascript that i want to reduce. See code below. message with 6 or more digits is verified, fewer is unverified. I group them by group.
const myArray = [
{ group: 'groupA', message: 'Text without a number', sl: '1A' },
{ group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
{ group: 'groupB', message: 'Text without a number', sl: '1A' },
{ group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
{ group: 'groupB', message: 'Text with a number WO5467829', sl: '1A' },
{ group: 'groupC', message: 'Text without a number', sl: '1B' },
{ group: 'groupD', message: 'Text with a number Tick0127866', sl: '1B' },
{ group: 'groupC', message: 'Text without a number', sl: '1A' }
];
output = myArray.reduce((acc, line) => {
let yes = 0;
let no = 0;
line.message.match(/\d{6,}/) ? yes++ : no++;
acc[line.group] = acc[line.group] || {};
acc[line.group].verified = (acc[line.group].verified || 0) + yes;
acc[line.group].unverified = (acc[line.group].unverified || 0) + no;
return acc;
}, {});
console.log('output', output);
However I would like the output to also be an array of objects like so:
[
{ group: 'groupA', verified: 2, unverified: 1 },
{ group: 'groupB', verified: 1, unverified: 1 },
{ group: 'groupC', verified: 0, unverified: 2 },
{ group: 'groupD', verified: 1, unverified: 0 }
]
How would I do this?
Share asked Jan 27, 2020 at 16:46 earl dukeearl duke 517 bronze badges 3-
2
Change the logic and use an array (
myArray.reduce((acc, line) => ..., [])
), or convert the result afterwards withObject.entries()
+.map()
– Andreas Commented Jan 27, 2020 at 16:50 - Can you provide some context regarding why you are trying to achieve? What do you use/need the verified and unverified properties for? – Rob Monhemius Commented Jan 27, 2020 at 16:59
- Thanks for the swift answers guys! I'll be using the output as input to a d3.js stacked bar chart with monthly figures. – earl duke Commented Jan 27, 2020 at 17:16
6 Answers
Reset to default 3Use an array as the initial value of your accumulator and inside .reduce
, use findIndex
to check for the current group, if found, update verified
and unverified
values, otherwise, insert a new one :
const myArray = [
{ group: "groupA", message: "Text without a number", sl: "1A" },
{ group: "groupA", message: "Text with a number WO5467829", sl: "1A" },
{ group: "groupB", message: "Text without a number", sl: "1A" },
{ group: "groupA", message: "Text with a number WO5467829", sl: "1A" },
{ group: "groupB", message: "Text with a number WO5467829", sl: "1A" },
{ group: "groupC", message: "Text without a number", sl: "1B" },
{ group: "groupD", message: "Text with a number Tick0127866", sl: "1B" },
{ group: "groupC", message: "Text without a number", sl: "1A" }
];
output = myArray.reduce((acc, line) => {
let yes = 0;
let no = 0;
line.message.match(/\d{6,}/) ? yes++ : no++;
// check if you have the group in the accumulator
const ndx = acc.findIndex(e => e.group === line.group);
// if you have it, manipulate verified and unverified
if (ndx > -1) {
acc[ndx].verified = (acc[ndx].verified || 0) + yes;
acc[ndx].unverified = (acc[ndx].unverified || 0) + no;
} else {
// insert a new entry instead
acc.push({
group: line.group,
verified: yes,
unverified: no
});
}
return acc;
}, []); // use an array as the initial value of the accumulator
console.log(output);
You can simply extend your solution/output to get the actual required output using Object.entries()
or Object.keys()
. I am going to use Object.entries()
const myArray = [
{ group: 'groupA', message: 'Text without a number', sl: '1A' },
{ group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
{ group: 'groupB', message: 'Text without a number', sl: '1A' },
{ group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
{ group: 'groupB', message: 'Text with a number WO5467829', sl: '1A' },
{ group: 'groupC', message: 'Text without a number', sl: '1B' },
{ group: 'groupD', message: 'Text with a number Tick0127866', sl: '1B' },
{ group: 'groupC', message: 'Text without a number', sl: '1A' }
];
output = myArray.reduce((acc, line) => {
let yes = 0;
let no = 0;
line.message.match(/\d{6,}/) ? yes++ : no++;
acc[line.group] = acc[line.group] || {};
acc[line.group].verified = (acc[line.group].verified || 0) + yes;
acc[line.group].unverified = (acc[line.group].unverified || 0) + no;
return acc;
}, {});
console.log('output', output);
const actualOutput = Object.entries(output).map(([group, value]) => ({group, ...value }));
console.log(actualOutput);
I couldn't resist refactoring your code a little. That said. what I have done:
- initiate the accumulator with an array (
[]
) - push a group to the array if it is not yet initialised
- increment
verified
orunverified
depending whether your test fails
const myArray = [
{ group: "groupA", message: "Text without a number", sl: "1A" },
{ group: "groupA", message: "Text with a number WO5467829", sl: "1A" },
{ group: "groupB", message: "Text without a number", sl: "1A" },
{ group: "groupA", message: "Text with a number WO5467829", sl: "1A" },
{ group: "groupB", message: "Text with a number WO5467829", sl: "1A" },
{ group: "groupC", message: "Text without a number", sl: "1B" },
{ group: "groupD", message: "Text with a number Tick0127866", sl: "1B" },
{ group: "groupC", message: "Text without a number", sl: "1A" }
];
output = myArray.reduce((acc, line) => {
if( acc.findIndex(e => e.group === line.group) === -1 ) {
acc.push({
group: line.group,
verified: 0,
unverified: 0
});
}
let group = acc.find(e => e.group === line.group);
if( line.message.match(/\d{6,}/) )
group.verified++;
else
group.unverified++;
return acc;
}, []);
console.log(output);
Put the group
prop in your acc.
Then use Object.values
function to return the values of an object.
const myArray = [
{ group: 'groupA', message: 'Text without a number', sl: '1A' },
{ group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
{ group: 'groupB', message: 'Text without a number', sl: '1A' },
{ group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
{ group: 'groupB', message: 'Text with a number WO5467829', sl: '1A' },
{ group: 'groupC', message: 'Text without a number', sl: '1B' },
{ group: 'groupD', message: 'Text with a number Tick0127866', sl: '1B' },
{ group: 'groupC', message: 'Text without a number', sl: '1A' }
];
output = myArray.reduce((acc, line) => {
let yes = 0;
let no = 0;
line.message.match(/\d{6,}/) ? yes++ : no++;
acc[line.group] = acc[line.group] || {};
acc[line.group].group = line.group;
acc[line.group].verified = (acc[line.group].verified || 0) + yes;
acc[line.group].unverified = (acc[line.group].unverified || 0) + no;
return acc;
}, {});
console.log('output', Object.values(output));
You can use map()
on Object.entries
. I also refactored your code in reduce
method
const myArray = [
{ group: 'groupA', message: 'Text without a number', sl: '1A' },
{ group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
{ group: 'groupB', message: 'Text without a number', sl: '1A' },
{ group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
{ group: 'groupB', message: 'Text with a number WO5467829', sl: '1A' },
{ group: 'groupC', message: 'Text without a number', sl: '1B' },
{ group: 'groupD', message: 'Text with a number Tick0127866', sl: '1B' },
{ group: 'groupC', message: 'Text without a number', sl: '1A' }
];
let output = myArray.reduce((acc, line) => {
acc[line.group] = acc[line.group] || {verified: 0, unverified: 0};
if(line.message.match(/\d{6,}/)){
acc[line.group].verified++
}
else{
acc[line.group].unverified++
}
return acc;
}, {});
output = Object.entries(output).map(([k, v]) => ({group: k, ...v}))
console.log('output', output);
Use reduce in bination with regex testing like this -
const myArray = [{
group: 'groupA',
message: 'Text without a number',
sl: '1A'
},
{
group: 'groupA',
message: 'Text with a number WO5467829',
sl: '1A'
},
{
group: 'groupB',
message: 'Text without a number',
sl: '1A'
},
{
group: 'groupA',
message: 'Text with a number WO5467829',
sl: '1A'
},
{
group: 'groupB',
message: 'Text with a number WO5467829',
sl: '1A'
},
{
group: 'groupC',
message: 'Text without a number',
sl: '1B'
},
{
group: 'groupD',
message: 'Text with a number Tick0127866',
sl: '1B'
},
{
group: 'groupC',
message: 'Text without a number',
sl: '1A'
}
];
const numberRegex = /[0-9]{6}/;
const res = Object.values(myArray.reduce((acc, curr) => {
const { group, message } = curr;
const isPhoneVerified = numberRegex.test(message);
if (!acc[group] && isPhoneVerified) {
acc[group] = { group: group, verified: 1, unverified: 0 };
} else if (!acc[group] && !isPhoneVerified) {
acc[group] = { group: group, verified: 0, unverified: 1 };
} else if (acc[group] && isPhoneVerified) {
acc[group].verified += 1;
} else if (acc[group] && !isPhoneVerified) {
acc[group].unverified += 1;
}
return acc;
}, {}));
console.log(res);
本文标签: Reduce array of objects in javascriptStack Overflow
版权声明:本文标题:Reduce array of objects in javascript - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744930727a2632881.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论