Hi,
I have these 2 arrays of objects:
const arr1 = [{"id":"pear","qty":2},{"id":"apple","qty":2}];
const arr2 = [{"id":"pear","qty":5},{"id":"lemon","qty":1}];
I want to combine them but at the same time summing their values in qty when they have the same id so this is the expected output:
[{"id":"pear","qty":7},{"id":"apple","qty":2},{"id":"lemon","qty":1}];
I tried this but it only keeps the first object:
const newArray = arr1.map((obj) => {
const secondArrayObj = arr2.find((obj2) => obj2.id === obj.id);
if (secondArrayObj) {
return {...secondArrayObj, ...obj}
}
return null;
}).filter((obj) => obj != null);
console.log(newArray);
What is the best approach here?
Thank you.
For your code,the reason is that you are using Array.map(),it will only covnert arr1 to another array,and will not merge arr2
To solve it,we can do it via Array.reduce() and Array.filter()
const arr1 = [{"id":"pear","qty":2},{"id":"apple","qty":2}];
const arr2 = [{"id":"pear","qty":5},{"id":"lemon","qty":1}];
let arr3 = [...arr1,...arr2]
arr3 = arr3.reduce((a,v) => {
let obj = a.find(i => i.id === v.id)
if(obj){
obj.qty += v.qty
}else{
a.push(v)
}
return a
},[])
console.log(arr3)
There are several ways to skin the cat. Here is one that uses an intermediate sums object, which performs well with large arrays:
const arr1 = [{"id":"pear","qty":2},{"id":"apple","qty":2}];
const arr2 = [{"id":"pear","qty":5},{"id":"lemon","qty":1}];
let sums = {};
arr1.concat(arr2).forEach(obj => {
if(!sums[obj.id]) {
sums[obj.id] = 0;
}
sums[obj.id] += obj.qty;
});
let arr3 = Object.keys(sums).map(id => { return {id: id, qty: sums[id]}; });
console.log(arr3);
Output:
[
{
"id": "pear",
"qty": 7
},
{
"id": "apple",
"qty": 2
},
{
"id": "lemon",
"qty": 1
}
]
Combine both arrays
Reduce them to a map keyed by id and value being the sum of qty
Turn that object back into an array using Object.entries()
Map that back to an array of objects
const arr1 = [{"id":"pear","qty":2},{"id":"apple","qty":2}];
const arr2 = [{"id":"pear","qty":5},{"id":"lemon","qty":1}];
const newArray = [
...arr1
.concat(arr2)
.reduce(
(map, { id, qty }) => map.set(id, qty + (map.get(id) ?? 0)),
new Map()
),
].map(([id, qty]) => ({ id, qty }));
console.log(newArray);
.as-console-wrapper { max-height: 100% !important; }
Related
I have an array of objects as follows
const array = [
{id:1,parentIds:[]}
{id:2,parentIds:[1,3]}
{id:3,parentIds:[1,2,4]}
]
How can I make it possible to remove an object's parentIds value if it doesn't exist in the array? to look something like this
const array = [
{id:1,parentIds:[]}
{id:2,parentIds:[1,3]}
{id:3,parentIds:[1,2]}
]
You can try this solution:
const array = [{
id: 1,
parentIds: []
}, {
id: 2,
parentIds: [1, 3]
}, {
id: 3,
parentIds: [1, 2, 4]
}];
const idsArr = new Set(array.map(el => el.id));
array.forEach(el => {
el.parentIds = el.parentIds.filter(el => idsArr.has(el));
})
console.log(array);
It's better to avoid mutating the original array parentIds, use immutation to create new array:
const array = [
{id:1,parentIds:[]},
{id:2,parentIds:[1,3]},
{id:3,parentIds:[1,2,4]}
]
const ids = array.map(({id}) => id)
const newArray = array.map(({parentIds,...arrayItemRest}) => {
const newparentIds = parentIds.filter(id => ids.includes(id))
return {
...arrayItemRest,
parentIds: newparentIds
}
})
const array = [
{id:1,parentIds:[]},
{id:2,parentIds:[1,3]},
{id:3,parentIds:[1,2,4]}
]
// Let's create an array only containing the ids
var ids = array.map(o => o.id)
// Loop array
array.forEach((object) => {
// Loop all parent ids
object.parentIds.forEach((id, index) => {
// Check if we find the id in our list
if (ids.indexOf(id) === -1) {
// Delete item from array if not found
object.parentIds.splice(index, 1)
}
})
})
// The result
console.log(array)
You can map (documentation here) your parent Ids and then filter using the includes method (documentation here)
const array = [{
id: 1,
parentIds: []
},
{
id: 2,
parentIds: [1, 3]
},
{
id: 3,
parentIds: [1, 2, 4]
}
]
const parents = array.map(x => x.id)
array.forEach(item => {
item.parentIds = item.parentIds.filter(x => parents.includes(x))
})
console.log(array)
Get a list of keys/ids using map, and then map over the array of objects to filter out the parentIds that are missing, returning a new array of updated objects.
const data=[{id:1,parentIds:[]},{id:2,parentIds:[1,3]},{id:3,parentIds:[1,2,4]}];
function removeIds(data) {
// Get the ids from all the array objects
const keys = data.map(obj => obj.id);
// `map` over the array and return a new
// array of updated objects
return data.map(obj => {
const newIds = obj.parentIds.filter(id => {
return keys.includes(id);
});
return { ...obj, parentIds: newIds };
});
}
console.log(removeIds(data));
Well basic way would be to go trough array every time there is a change, and update parentIds list.
To do that:
const dummyArray = [
{id:1,parentIds:[]},
{id:2,parentIds:[1,3]},
{id:3,parentIds:[1,2,4]}
];
/* You can do this with regular array, this only ensures that ids are unique */
const idsSet = new Set();
dummyArray.forEach(it => idsSet.add(it.id));
dummyArray.forEach(it => {
/* If you are using array, you would need to loop trough for each id and check if existing */
const newParentIds = it.parentIds.filter(id => idsSet.has(id));
it.parentIds = newParentIds;
console.log(it.parentIds);
});
There would be a better solution for this for sure, so please try to take this as an example for logic which can be used.
const array = [
{ id: 1, parentIds: [] },
{ id: 2, parentIds: [1, 3] },
{ id: 3, parentIds: [1, 2, 4] },
];
const removeParentIds = (array) => {
return array.map((item) => {
const { parentIds } = item;
return {
...item,
parentIds: parentIds.filter((parentId) => array.some((item) => item.id === parentId)),
};
});
}
console.log(removeParentIds(array));
You can add childIds in each object, so when you remove one object you can go through each of child's and remove from it's parents as-well.
const array = [
{id:1,parentIds:[],childIds:[2,3]},
{id:2,parentIds:[1,3],childIds:[3]},
{id:3,parentIds:[1,2],childIds:[2]}
]
function idChecker(id){
for(let i=0; i<array.length;i++) if(array[i].id === id) return i;
return undefined
}
function removeObject(id){
let key = idChecker(id)
if(key === undefined) return false
let children = array[key].childIds
children.map(val => {
let keyOfVal = idChecker(val)
array[keyOfVal].parentIds.splice(array[keyOfVal].parentIds.indexOf(id), 1)
})
array.splice(idChecker(id), 1)
return true
}
Loop through inner parentIds array and remove members that are not any of the outer ids.
const array = [
{ id: 1, parentIds: [] },
{ id: 2, parentIds: [1, 3] },
{ id: 3, parentIds: [1, 2, 4] }
];
array.forEach(
(o) =>
(o.parentIds = o.parentIds.filter((pI) =>
array.map((o) => o.id).includes(pI)
))
);
console.log(array);
How to create array of object from two different length of array
for example
arr1 = ["first","second","third","fourth","fifth","Sixth"]
arr2 = [["1","2","3","4","5","6"],["7","8","9","10","11","12"],["1","2","3","4"]]
finalArray = [{
first:1,
second:2
third:3,
fourth:4,
fifth:5,
sixth:6
},{
first:7,
second:8
third:9,
fourth:10,
fifth:11,
sixth:12
}]
I tried this using map but getting every key value pair as whole object
example
[
{first: 1}
{second: 2}
{third: 3}
{fourth: 4}
]
With map() and reduce():
const arr1 = ["first", "second", "third", "fourth", "fifth", "Sixth"];
const arr2 = [["1", "2", "3", "4", "5", "6"],
["7", "8", "9", "10", "11", "12"],
["1", "2", "3", "4"]];
const res = arr2.map(v => v.reduce((a, v, i) => ({...a, [arr1[i]]: v}), {}));
console.log(res);
You can take advantage of Array.prototype.reduce to update the shape of the result array
let arr1 = ["first","second","third","fourth","fifth","Sixth"];
let arr2 = [["1","2","3","4","5","6"],["7","8","9","10","11","12"],["1","2","3","4"]];
let result = arr2.reduce((accumulator, current) => {
let obj = arr1.reduce((acc, currentKey, index) => {
if(current.indexOf(index) && current[index] !== undefined ){
acc[[currentKey]] = current[index];
}
return acc;
}, {});
return accumulator.concat(obj);
}, []);
console.log(result);
without reduce() and covered edge case when the arr1 contains fewer elements as the element from arr2
const arr1 = ["first","second","third","fourth","fifth","Sixth"]
const arr2 = [["1","2","3","4","5","6"],["7","8","9","10","11","12"],["1","2","3","4"]]
const res = arr2.map(values => {
const res = {}
for(const [index, value] of arr1.entries()){
if(values[index]) {
res[value] = values[index] // or parseInt(values[index])
} else {
break
}
}
return res
})
console.dir(res)
I want to filter following two arrays and get the count of "isimplemented: 'Yes'" elements:
const arr1 = [{ProjectName: "IT", Department: "Software"}]
const arr2 = [{Name: "IT", isimplemented: "Yes"}]
I tried the following method to do the same but not getting desired result. How I can do it in JavaScript
((arr1.map(data => data.ProjectName)).filter(arr1.map(data => data.ProjectName) === arr2.map(data => data.Name) && isimplemented === "Yes")).length
You could teka a Set for the implemented projects and then count the occurences of the project who are implemented.
const
arr1 = [{ ProjectName: "IT", Department: "Software" }],
arr2 = [{ Name: "IT", isimplemented: "Yes" }],
implemented = arr2.reduce((s, { Name, isimplemented }) => isimplemented === 'Yes' ? s.add(Name) : s, new Set),
count = arr1.reduce((c, { ProjectName }) => c + implemented.has(ProjectName), 0);
console.log(count);
First merge the different arrays to create one single array
Create a variable which will keep track of your count
use forEach to iterate over the elements in the array, increment the count for every array-object having property isImplemented: 'Yes'
const arr1 = [{ProjectName: "IT", Department: "Software"}]
const arr2 = [{Name: "IT", isimplemented: "Yes"}]
const newArr = [...arr1, ...arr2]
let count = 0
newArr.forEach(element => {
if (element.isimplemented === 'Yes') {
count++
}
})
console.log(count)
i have this json:
[
{
"AF28110": 33456.75,
"AF27989": 13297.26
}
]
and i want to convert it to:
[
{ "name": "AF28110", "price": 33456.75},
{ "name": "AF27989", "price": 13297.26}
]
I have tried various making it with .map() but i cannot make it work.
does anyone have any idea how to do this?
thank you
You can try following code:
let output = [];
input.forEach(obj => Object.getOwnPropertyNames(obj).forEach(key => output.push({name: key, price: obj[key]})))
Object.getOwnPropertyNames will give you names of your properties and then you can transform each name to a separate output array item.
Using map:
const data = [
{
"AF28110": 33456.75,
"AF27989": 13297.26
}
]
const out = Object.keys(data[0]).map(el => {
return { name: el, price: data[0][el] };
});
console.log(out)
Here's a way using concat, Object.keys, and map. You can take each item from the array, get the keys from that object, and then map each key to the name/price object you want. Do that for each item, then flatten the result (using concat).
Example:
const arr = [{
"AF28110": 33456.75,
"AF27989": 13297.26
}]
const result = [].concat(...arr.map(o => Object.keys(o).map(k => ({name: k, price: o[k]}))))
console.log(result);
If you have multiple objects on the array, you can use reduce
let arr = [
{"AF28110": 33456.75,"AF27989": 13297.26},
{"AF28111": 33456.20,"AF27984": 13297.88}
];
let result = arr.reduce((c, v) => c.concat(Object.entries(v).map(o => {return {name: o[0],price: o[1]}})), []);
console.log(result);
Try this,
var text = '[{"AF28110": 33456.75,"AF27989": 13297.26}]';
var obj = JSON.parse(text);
var result = [];
for (i = 0; i < obj.length; i++) {
var keys = Object.keys(obj[i]);
for (j = 0; j < keys.length; j++){
result[j] = '{ "name":' +keys[j] + ', "price":' + obj[i][keys[j]]+'}';
}
}
console.log(result);
Thanks.
Ways to achieve :
Using Object.keys method :
var jsonObj = [
{
"AF28110": 33456.75,
"AF27989": 13297.26
}
];
var res = Object.keys(jsonObj[0]).map(item => {
return {"name": item, "price": jsonObj[0][item] };
});
console.log(res);
Using Object.getOwnPropertyNames method :
var jsonObj = [
{
"AF28110": 33456.75,
"AF27989": 13297.26
}
];
var res = Object.getOwnPropertyNames(jsonObj[0]).map(item => {
return {"name": item, "price": jsonObj[0][item] };
});
console.log(res);
I'm new to StackOverflow and I know this post might possibly be a duplicate of another so please spare me with all the downvotes and if you think there's an answer to my question out there, please post it and I'll delete this question. Thanks for understanding.
var array1 = ["name", "title", "desc"]
var array2 = [["name1", "name2"], ["title1", "title2"],["desc1", "desc2"]]
How will I turn these into:
[
{name: "name1", title: "title1", desc: "desc1"},
{name: "name2", title: "title2", desc: "desc2"}
]
You can use Array#map, Object.assign (with spread syntax) and the ES6 computed property syntax to achieve that:
const array1 = ["name", "title", "desc"],
array2 = [["name1", "name2"], ["title1", "title2"],["desc1", "desc2"]];
const result = array2[0].map( (_, j) =>
Object.assign(...array1.map( (key, i) => ({ [key]: array2[i][j] }) ))
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
const result = [];
for(const [index, key] of array1.entries()){
for(const [userindex, value] of array2[index].entries()){
if(!result[userindex])
result[userindex] = {};
result[userindex][key] = value;
}
}
You might go over every key and the values related to the key and assign every key/value pair to the resulting object at the position of the value.
You could reduce the given values array by using the keys as key and the value for new objects.
var keys = ["name", "title", "desc"],
values = [["name1", "name2"], ["title1", "title2"],["desc1", "desc2"]],
objects = values.reduce((r, a, i) => {
a.forEach((v, j) => Object.assign(r[j] = r[j] || {}, { [keys[i]]: v }));
return r;
}, []);
console.log(objects);
You can use this way also:
var array1 = ["name", "title", "desc"];
var array2 = [["name1", "name2"], ["title1", "title2"],["desc1", "desc2"]];
var res = [];
for(var i=0; i<array2[0].length; i++){
var obj = {};
for(var j=0; j<array1.length; j++){
var key = array1[j];
var value = array2[j][i];
obj[key] = value;
}
res.push(obj);
}
console.log(res);