This question already has answers here:
Sum values of objects in array
(8 answers)
Closed 1 year ago.
In JavaScript, suppose I have:
list1=[
{name='Mark',count='3'}
{name='Harry',count='2'}
]
list2=[
{name='John',count='3'}
{name='Mark',count='1'}
]
list3=[
{name='John',count='3'}
{name='Harry',count='1'}
]
and I want an intersection of the list that adds "count" of the same "name" items
result:
listResult=[
{name='Mark',count='4'}
{name='Harry',count='3'}
{name='John',count='6'}
How would I proceed?
You could use Array.reduce to create a map of the name counts, then use Object.values to return the desired result.
We first of all concatenate the lists ([list1, list2, list2].flat()), then use .reduce to create our map keyed on item name.
const list1=[ {name:'Mark',count:'3'}, {name:'Harry',count:'2'} ]
const list2=[ {name:'John',count:'3'}, {name:'Mark',count:'1'} ]
const list3=[ {name:'John',count:'3'}, {name:'Harry',count:'1'} ]
const result = Object.values([list1, list2, list3].flat().reduce((acc, curr) => {
if (!acc[curr.name]) acc[curr.name] = { name: curr.name, count: 0};
acc[curr.name].count += (+curr.count);
return acc;
}, {}));
console.log(result)
The json above are not valid, but here i got what you wanted.
Have a look below
var list1=[
{name:'Mark',count:'3'},
{name:'Harry',count:'2'}
]
var list2=[
{name:'John',count:'3'},
{name:'Mark',count:'1'}
]
var list3=[
{name:'John',count:'3'},
{name:'Harry',count:'1'}
]
var result = [];
function counter(list){
list.forEach(x=>{
var f = result.find(a=> a.name == x.name);
if (f)
f.count=parseInt(f.count)+parseInt(x.count);
else result.push(x);
})
return result;
}
counter(list1)
counter(list2)
counter(list3)
console.log(result)
Related
This question already has answers here:
How to add index values of array in object to a key
(7 answers)
Closed 4 months ago.
I've a data like this.
const arr = [
{name:'john'},
{name:'jeff'},
{name:'bob'},
{name:'peter'},
]
arr.forEach((v,i,a)=>{
console.log(v)
})
And I want to transfer to
arr = [{id:1,name:john},{id:2,name:jeff},{id:3,name:bob},{id:4,name:peter}]
I want to add id to every object in array.
How to solves this, Thank you.
const arr = [
{name:'john'},
{name:'jeff'},
{name:'bob'},
{name:'peter'},
]
arr.forEach((v,i,a)=>{
v.id = i + 1
})
console.log(arr)
Try this :
const arr = [
{name:'john'},
{name:'jeff'},
{name:'bob'},
{name:'peter'},
];
const res = arr.map((obj, index) => {
return {
...obj,
id: index + 1
}
});
console.log(res);
I am trying to merge some JSON data sets BY key value WHILE including duplicate values WHERE the key matches.
I have tried this quite a bit now but can't seem to produce the object that I need.
Object 1
[
{"userId":"1",
"email":"email1#gmail.com"
},
{"userId":"2",
"email":"email2#gmail.com"
}
]
Object 2
[
{"id":"1abc",
"listingId":"4def",
"userId":"2"
},
{"id":"2abc",
"listingId":"2def",
"userId":"1"
},
{"id":"3abc",
"listingId":"3def",
"userId":"2"
}
]
I need to merge these objects in a way that looks like this:
Desired Output
[
{"id":"1abc",
"listingId":"4def",
"userId":"2",
"email":"email2#gmail.com"
},
{"id":"2abc",
"listingId":"2def",
"userId":"1",
"email":"email1#gmail.com"
},
{"id":"3abc",
"listingId":"3def",
"userId":"2",
"email":"email2#gmail.com"
}
]
Problems I am Experiencing
I am able to merge the data sets successfully using a function that looks like this:
function merge(a, b, key) {
function x(a) {
a.forEach(function (b) {
if (!(b[key] in obj)) {
obj[b[key]] = obj[b[key]] || {};
array.push(obj[b[key]]);
}
Object.keys(b).forEach(function (k) {
obj[b[key]][k] = b[k];
});
});
}
var array = [],
obj = {};
x(a);
x(b);
return array;
}
https://stackoverflow.com/a/35094948/1951144
But it produces results that look like this:
[
{"id":"1abc",
"listingId":"4def",
"userId":"2",
"email":"email2#gmail.com"
},
{"id":"2abc",
"listingId":"2def",
"userId":"1",
"email":"email1#gmail.com"
}
]
Is there a way to use the above function WHILE keeping AND including the duplicate values where my keys match?
For each element in arr2, create a new element containing the props of the item from arr2, and the email of the corresponding entry in arr1.
let arr1 = [
{"userId":"1",
"email":"email1#gmail.com"
},
{"userId":"2",
"email":"email2#gmail.com"
}
];
let arr2 = [
{"id":"1abc",
"listingId":"4def",
"userId":"2"
},
{"id":"2abc",
"listingId":"2def",
"userId":"1"
},
{"id":"3abc",
"listingId":"3def",
"userId":"2"
}
];
let output = arr2.map(a2 => ({...a2, email: arr1.find(a1 => a1.userId === a2.userId)?.email}));
console.log(output);
This solution works even if the key isn't known yet. .flatMap() both arrays and pass in the desired key (in example it's "userId"). Use Object.entries() on each object so they will be an array of pairs.
[{A1: A1v}, {A2: A2v},...]
// into
[[A1, A1v], [A2, A2v],...]
.flatMap() the second array and on each iteration .flatMap() the first array. Then compare the given key ("userID") with the key of each object from the second array ("a") AND the value of that key and the value of the key of the object in the first array.
a === key && av === bv
If both criteria are meet then merge those objects and return it, otherwise...
? {...objA, ...objB}
return an empty array, which ultimately results to nothing since .flatMap() flattens one level of arrays.
: []
const arrA=[{userId:"1",email:"email1#gmail.com"},{userId:"2",email:"email2#gmail.com"}];const arrB=[{id:"1abc",listingId:"4def",userId:"2"},{id:"2abc",listingId:"2def",userId:"1"},{id:"3abc",listingId:"3def",userId:"2"}];
function masterKey(primary, key, secondary) {
let result = secondary.flatMap(objB => Object.entries(objB).flatMap(([b, bv]) =>
primary.flatMap(objA => Object.entries(objA).flatMap(([a, av]) =>
a === key && av === bv ? {...objA, ...objB} : []))));
return result;
}
console.log(masterKey(arrA, "userId", arrB));
I have an array of objects and I want to be able to sort them by their "site" value into pairs. There can't be more that 2 objects in each child array so if there is 3 matches I get 1 child array with 2 objects and 1 child array with 1 object.
I have:
[{site:'A'}, {site:'A'}, {site:'B'}, {site:'B'}, {site:'B'}];
I want:
[[{site:'A'}, {site:'A'}],[{site:'B'}, {site:'B'}], [{site:'B'}]]
Whats the best way to do this? any help is appreciated.
This should work for you
function sortArray(arr){
arr.sort((a,b)=>a.site > b.site ? 1 : -1) // Sorting the array to have consecutive values
let chunks = [];
for(let i = 0;i<arr.length;i+=2){
if(arr[i]?.site == arr[i+1]?.site) chunks.push(arr.slice(i,i+2));
else {
chunks.push([arr[i]]);
i--;
}
}
return chunks;
}
let arr = [{site:'A'}, {site:'A'}, {site:'B'}, {site:'B'}, {site:'B'}];
console.log(sortArray(arr))
Using reduce ;) :
const a = [{
site: 'A'
}, {
site: 'A'
}, {
site: 'B'
}, {
site: 'B'
}, {
site: 'B'
}];
var r = a.reduce((ac, x) => ({
...ac,
[x.site]: [...(ac[x.site] || []), x]
}), {})
var r2 = Object.values(r).flatMap(x =>
x.reduce((ac, z, i) => {
if (i % 2) {
ac[i - 1].push(z)
return ac
}
return [...ac, [z]]
}, []))
console.log(r2)
PS: Since this is hard to read I'd suggest to use lodash (specifically groupBy and chunk methods)
It's kind of a 'groupBy' operation (as seen in underscore or lodash). Those produce an object keyed by the values being grouped. Consider writing it that way for general use. To get the shape the OP is looking for, strip out the values of that result...
function groupBy(array, key) {
return array.reduce((acc, el) => {
let value = el[key];
if (!acc[value]) acc[value] = [];
acc[value].push(el);
return acc;
}, {});
}
let array = [{site:'A'}, {site:'A'}, {site:'B'}, {site:'B'}, {site:'B'}];
let grouped = groupBy(array, 'site'); // produces { A: [{site:'A'} ...], B: ... }
let groups = Object.values(grouped)
console.log(groups)
This question already has an answer here:
How to filter an array of arrays?
(1 answer)
Closed 3 years ago.
I have following array of arrays showing employee name, id and department
var employees = [
["John","001","Sales"]
["Mike","002","Sales"]
["Adam","003","Eng"]
["Sam","004","Sales"]
["Emma","005","Eng"]
];
how can I get specific column from this array based on another column. For example, I would like to get ID numbers column for all 'Eng' department where result would be:
["003","005"]
At first you need to filter your array and then just get necessary values through map method:
var employees = [
["John","001","Sales"],
["Mike","002","Sales"],
["Adam","003","Eng"],
["Sam","004","Sales"],
["Emma","005","Eng"]
];
const result = employees.filter(f=> f.some(s=>s == 'Eng')).map(([a, b, c]) => b);
console.log(result);
You can use map() on the array to filter through and get the data you want.
var employees = [
["John", "001", "Sales"],
["Mike", "002", "Sales"],
["Adam", "003", "Eng"],
["Sam", "004", "Sales"],
["Emma", "005", "Eng"]
];
function getColumnFor(data, dept) {
const output = [];
data.map(function (item) {
if (item[2].toLowerCase() === dept.toLowerCase()) {
output.push(item[1]);
}
});
return output;
}
const result = getColumnFor(employees, "Eng");
console.log(result);
If your array in formate, you can do as below
var employees = [
["John","001","Sales"],
["Mike","002","Sales"],
["Adam","003","Eng"],
["Sam","004","Sales"],
["Emma","005","Eng"]
];
var codes = [];
for(var k in employees){
if(employees[k][2] == 'Eng'){
codes.push(employees[k][1]);
}
}
console.log(codes);
[["Django UnChainers","AA-24010"],["General","AA-26191"]]
I have one array in above form. I want to retrieve all the value with prefix AA (which are in the second position). Is there any way where I can fetch the value by passing prefix?.
I know the way where I can get the value by passing index but may be tomorrow index can get change so is it possible to fetch the value by passing prefix?
In case OP wants a function to do this.
function(arr, pattern){
return arr.map(function(x){
return x.filter( word => ~ word.indexOf(pattern))
});
}
var arr =
[ [ "Django UnChainers", "AA-24010" ], [ "General", "AA-26191" ]];
var list = arr.map(function(x){
if(~(x[1].indexOf('AA'))){
return x[1];
}
});
console.log(list);
In case the index changes in future, iterate through each string and check for the "AA" string. Check the below code.
var arr =
[ [ "Django UnChainers", "AA-24010" ], [ "General", "AA-26191" ]];
var list = arr.map(function(x){
return x.filter( word => ~ word.indexOf('AA'))
});
console.log(list);
this is shorter
var = [nested array]
a.filter(x => x[1].startsWith('AA'))
//in case you are not sure about the index
a.filter(x => x.filter(y => y.startsWith('AA').length > 0))