How to group array of object by key value pairs using javaScript? - javascript

I just started learning JavaScript, I have this type of array, how I can turn this array of objects into key-value pairs like below, Any source and reference is acceptable.
Sample Array:
[
{Id: "6d7e75e6-c58b-11e7-95-ac162d77eceb", qty: 1},
{Id: "6d2e75e6-c58b-11e7-95-ac162d77eceb", qty: 1}
]
Expected Result:
{
"6d7e75e6-c58b-11e7-95-ac162d77eceb":1,
"6d2e75e6-c58b-11e7-95-ac162d77eceb":1
}

Using Array.prototype.Reduce:
const arr = [{Id: "6d7e75e6-c58b-11e7-95-ac162d77eceb", qty: 1},{Id: "6d2e75e6-c58b-11e7-95-ac162d77eceb", qty: 1}];
const result = arr.reduce((acc, { Id, qty }) => ({ ...acc, [Id]: qty }), {});
console.log(result);

Another approach, a little more beginner friendly.
const arr = [
{Id: "6d7e75e6-c58b-11e7-95-ac162d77eceb", qty: 1},
{Id: "6d2e75e6-c58b-11e7-95-ac162d77eceb", qty: 1}
];
const newObject = {}; // empty object
// loop over each element of the array
arr.forEach(element => {
// the key is the element identifier (Id) and the value is the element quantity (qty)
newObject[element.Id] = element.qty;
});

You can use a loop and add the item.Id as the key and the item.qty as the value in an empty object.
let arr = [{Id: "6d7e75e6-c58b-11e7-95-ac162d77eceb", qty: 1},{Id: "6d2e75e6-c58b-11e7-95-ac162d77eceb", qty: 1}]
let obj = {}
arr.forEach(item => {
obj[item.Id] = item.qty
})
console.log(obj)

You can easily achieve this result using forEach in a single line of code.
const arr = [
{ Id: "6d7e75e6-c58b-11e7-95-ac162d77eceb", qty: 1 },
{ Id: "6d2e75e6-c58b-11e7-95-ac162d77eceb", qty: 1 },
];
const result = {};
arr.forEach(({ Id, qty }) => (result[Id] = qty));
console.log(result);

You can achieve the desired result with below code
//input array
const arrList = [
{Id: "6d7e75e6-c58b-11e7-95-ac162d77eceb", qty: 1},
{Id: "6d2e75e6-c58b-11e7-95-ac162d77eceb", qty: 1}
]
function findArray(arr) {
//define a new array to store Id's
let newArray = [];
//iterate through array items
arr.forEach(item => {
newArray.push(item.Id);
});
return newArray;
}
//call findArray function to get desired output
console.log(findArray(arrList));

Using Object.fromEntries()
const
array = [{ Id: "6d7e75e6-c58b-11e7-95-ac162d77eceb", qty: 1 }, { Id: "6d2e75e6-c58b-11e7-95-ac162d77eceb", qty: 1 }],
object = Object.fromEntries(array.map(({ Id, qty }) => [Id, qty]));
console.log(object);
or, for some fragile novelty...
const
array = [{ Id: "6d7e75e6-c58b-11e7-95-ac162d77eceb", qty: 1 }, { Id: "6d2e75e6-c58b-11e7-95-ac162d77eceb", qty: 1 }],
object = Object.fromEntries(array.map(Object.values));
console.log(object);

Related

How to insert each array item into each object of other array?

I have 2 arrays
I want this:
[{name: 'Sweater', qty: 1}, {name: 'Skirt', qty: 3}, {name: 'Socks', qty: 2}]
but I get
qtyList = [1, 3, 2]
data = [{name: 'Sweater', qty: 1}, {name: 'Skirt', qty: 1}, {name: 'Socks', qty: 1}]
let assignQty = data.map((x, id) => {
qtyList.map((y, idx) => {
if (idx == id) return x.qty = y
})
})
console.log('assignQty', assignQty)
You're essentially zipping the 2 lists together - typically done as follows:
const qtyList = [1, 3, 2]
const data = [{name: 'Sweater', qty: 1}, {name: 'Skirt', qty: 1}, {name: 'Socks', qty: 1}]
const result = data.map((item,idx) => ({...item, qty: qtyList[idx]}))
console.log(result);
const qtyList = [1, 3, 2];
data = [{name: 'Sweater', qty: 1}, {name: 'Skirt', qty: 1}, {name: 'Socks', qty: 1}]
const updateQuantity = (list, data) => {
if (data.length !== list.length) {
return
}
for (let index = 0; index < list.length; index++) {
const element = list[index];
// udpate data
data[index] = {
name: data[index].name,
qty: element
}
}
return data;
}
console.log(updateQuantity(qtyList, data));
Use Spread syntax on item than change qty with array values
qtyList = [1, 3, 2]
data = [{name: 'Sweater', qty: 1}, {name: 'Skirt', qty: 1}, {name: 'Socks', qty: 1}]
let assignQty = data.map((item, index) => (
{
...item,
qty: qtyList[index]}
));
console.log("assignQty", assignQty );
Without using the spread operator, update the required field and then return x.
qtyList = [1, 3, 2]
data = [{name: 'Sweater', qty: 1}, {name: 'Skirt', qty: 1}, {name: 'Socks', qty: 1}]
var assignQty = data.map((x, id) => {x.qty=qtyList[id];return x;})
console.log('assignQty', assignQty)
This is my approach to your question. In your example, you were trying to map two arrays into one. This approach "loops" the data array containing the objects you want to change.
Using the index of each object it sets the item.qty to the value in qtyList[index].
qtyList = [1, 3, 2];
data = [{
name: 'Sweater',
qty: 1
}, {
name: 'Skirt',
qty: 1
}, {
name: 'Socks',
qty: 1
}];
let assignQty = data.map((item, index) => {
item.qty = qtyList[index];
return item;
});
console.log(assignQty)

Find objects that have duplicate names inside the array in JavaScript

I have an array that I find in the searchName section, and in the resultName section I separate the duplicate names, and in the filters section I want to display the objects that have those duplicate names in the console.log, but an empty array
Please help me to get the answer
const data = [
{id: 1,name: "Liam",age: 20},
{id: 1,name: "Noah",age: 22},
{id: 1,name: "Liam",age: 20},
{id: 1,name: "Elijah",age: 18},
{id: 1,name: "Elijah",age: 18}
]
const searchName = data.map(item => item.name)
console.log(searchName);
const toFindDuplicates = arry => arry.filter((item, index) => arry.indexOf(item) !== index);
const resultName = toFindDuplicates(searchName)
console.log(resultName);
const filters = data.filter(x => x.Name === resultName)
console.log(filters);
Use .includes() to check if the name of an element exists inside the resultName array. You also had a typo: x.name instead of x.Name
const data = [{
id: 1,
name: "Liam",
age: 20
},
{
id: 1,
name: "Noah",
age: 22
},
{
id: 1,
name: "Liam",
age: 20
},
{
id: 1,
name: "Elijah",
age: 18
},
{
id: 1,
name: "Elijah",
age: 18
}
]
const searchName = data.map(item => item.name)
console.log(searchName);
const toFindDuplicates = arry => arry.filter((item, index) => arry.indexOf(item) !== index);
const resultName = toFindDuplicates(searchName)
console.log(resultName);
const filters = data.filter(x => resultName.includes(x.name))
console.log(filters);
You need to fix your filter function.
In your version you trying to compare an array to an string.
What you need to do is something like this:
const filters = data.filter(x => resultName.includes(x.name))
First you can count the names and then fill the array
const data = [
{id: 1,name: "Liam",age: 20},
{id: 1,name: "Noah",age: 22},
{id: 1,name: "Liam",age: 20},
{id: 1,name: "Elijah",age: 18},
{id: 1,name: "Elijah",age: 18}
]
const obj = data.reduce((acc, el) => { acc[el.name] = (acc[el.name] ?? 0) + 1; return acc; }, {});
const all = Object.keys(obj);
const duplicates = Object.entries(obj).filter(el => el[1] > 1).map(el => el[0]);
const uniques = Object.entries(obj).filter(el => el[1] === 1).map(el => el[0]);
console.log(all);
console.log(duplicates);
console.log(uniques);

Filtering using two array of objects using JavaScript

I have an array as shown:
var arrOne = [{id: 3},{id: 8},{id: 12}];
And another array as shown:
var arrTwo = [
{id: 1, val: 'Adam'},
{id: 3, val: 'Bailey'},
{id: 8, val: 'Cathy'},
{id: 12, val: 'David'},
{id: 15, val: 'Earl'}
];
I want to iterate arrTwo based on arrOne, and get the val values out of arrTwo.
So the result should be:
var result = ['Bailey', 'cathy', 'David'];
Tried concatenating .map with .filter:
arrOne.map(arOne => arrTwo.filter(artwo => {
if(arOne.id === artwo.id) {
return artwo.val
} else {
return false;
}
}));
But it gives me all, and where it is false it adds false there, which I don't want.
Any ideas where I am going wrong will be appreciated.
Editing as per norbitrial's answer:
const arrOne = [{id: 3},{id: 8},{id: 12}];
const arrTwo = [
{id: 1, val: 'Adam'},
{id: 3, val: 'Bailey'},
{id: 8, val: 'Cathy'},
{id: 12, val: 'David'},
{id: 15, val: 'Earl'}
];
const result = arrOne.map(({id}) => arrTwo.find(e => {
const someCond = someConditionaEval();
if(someCond && e.id === id) {
return e;
} else {
return false;
}
}).val); //this breaks
Using .map() and .find() combination:
const arrOne = [{id: 3},{id: 8},{id: 12}];
const arrTwo = [{id: 1, val: 'Adam'}, {id: 3, val: 'Bailey'}, {id: 8, val: 'Cathy'}, {id: 12, val: 'David'}, {id: 15, val: 'Earl'}];
const result = arrOne.map(({id}) => arrTwo.find(e => e.id === id).val);
console.log(result);
I hope this helps!
You can use .filter() method on arrTwo and then using .includes() method get the filtered objects from arrTwo and then finally using .map() get only the val property values from each filtered object like:
var arrOne = [{id: 3},{id: 8},{id: 12}];
var arrTwo = [{id:1,val:"Adam"},{id:3,val:"Bailey"},{id:8,val:"Cathy"},{id:12,val:"David"},{id:15,val:"Earl"}];
var result = arrTwo.filter(a => arrOne.map(o=>o.id).includes(a.id)).map(o=>o.val)
console.log( result )
You could take an object with the values and then map the wanted values.
var arrOne = [{ id: 3 }, { id: 8 }, { id: 12 }],
arrTwo = [{ id: 1, val: 'Adam' }, { id: 3, val: 'Bailey' }, { id: 8, val: 'Cathy' }, { id: 12, val: 'David' }, { id: 15, val: 'Earl' }],
values = arrTwo.reduce((r, { id, val }) => (r[id] = val, r), {}),
result = arrOne.map(({ id }) => values[id]);
console.log(result);
Create a Map of val by id from arrTwo, and then map arrOne, and extract the val from the Map using the id.
Why I prefer creating a Map/dictionary (object) instead of using Array.map() with Array.find()?
Because of the complexity - Array.map() with Array.find(), for example, is O(n * m), while creating a Map and then using Array.map() to get the values is O(n + m). However, if you've got two small arrays, this shouldn't actually hurt actual performance.
const arrOne = [{id: 3},{id: 8},{id: 12}];
const arrTwo = [{id: 1, val: 'Adam'}, {id: 3, val: 'Bailey'}, {id: 8, val: 'Cathy'}, {id: 12, val: 'David'}, {id: 15, val: 'Earl'}];
const valById = new Map(arrTwo.map(({ id, val }) => [id, val]));
const result = arrOne.map(o => valById.get(o.id));
console.log(result);
Build an object from arrTwo to gather val's in one iteration.
use map on arrOne and get val from above object.
const update = (arr1, arr2) => {
const all = Object.fromEntries(arr2.map(({ id, val }) => [id, val]));
return arr1.map(({ id }) => all[id]);
};
var arrOne = [{ id: 3 }, { id: 8 }, { id: 12 }];
var arrTwo = [
{ id: 1, val: "Adam" },
{ id: 3, val: "Bailey" },
{ id: 8, val: "Cathy" },
{ id: 12, val: "David" },
{ id: 15, val: "Earl" }
];
console.log(update(arrOne, arrTwo));

Filter array of objects but return only specific properties - JS [duplicate]

This question already has answers here:
Extract certain properties from all objects in array
(5 answers)
Closed 4 months ago.
How to filter an array of objects with a condition and return only specific properties of filtered objects?
I know we can use filter followed by map to achieve this. But I am looking for more simple solution.
For ex:
let arr = [{name:"lala", id: 1}, {name: "coco", id:2}, {name: "lala", id:3}]
Suppose if I want only ids of name "lala".
Output should be,
[{id: 1}, {id: 3}]
The next simplest would be reduce
let arr = [{name:"lala", id: 1}, {name: "coco", id:2}, {name: "lala", id:3}];
console.log(
arr.reduce((values, value) =>
{
if (value.name === 'lala') values.push({ id: value.id });
return values;
}, [])
);
You can simply use Array.prototype.reduce to combine both mapping and filtering in the same operation. If you want to make it super concise, you can use object destructuring in the second argument of the reduce callback:
let arr = [{name:"lala", id: 1}, {name: "coco", id:2}, {name: "lala", id:3}];
let filteredMappedArr = arr.reduce((acc, { name, id }) => {
if (name === 'lala')
acc.push({ id });
return acc;
}, []);
console.log(filteredMappedArr);
filter followed by map is probably the most readable solution, but if you're looking to do it all in one step, you're looking at the classic for loop or using reduce.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
You can do it by using filter and map;
let arr = [{name:"lala", id: 1}, {name: "coco", id:2}, {name: "lala", id:3}]
let res = arr.filter(item => item.id % 2 === 1).map(item => ({id: item.id}))
console.log(res);
You could take Array#flatMap and return either a new obejct or an empty array which has no value for flattening.
let array = [{ name: "lala", id: 1 }, { name: "coco", id: 2 }, { name: "lala", id: 3 }],
result = array.flatMap(({ id, name }) => name === 'lala' ? [{ id }] : []);
console.log(result);
using .filter() and .map() functions:
let arr = [{name:"lala", id: 1}, {name: "coco", id:2}, {name: "lala", id:3}]
let newArr = arr.filter((elm) => (elm.name === 'lala')).map( (elm) => {return {id:elm.id}});
console.log(newArr);
let arr = [
{ name: "lala", id: 1 },
{ name: "coco", id: 2 },
{ name: "lala", id: 3 },
];
let a = [];
arr.filter(({ name, id }) => {
if (name === "lala") {
a.push({ id });
}
});
console.log(a);
with filter we check for the condition where name matches 'lala' if yes then we push id to new array...that's simple

Convert array of objects in an array of array of objects [duplicate]

This question already has answers here:
How can I group an array of objects by key?
(32 answers)
Closed 2 years ago.
I am retrieving data from a football (soccer) API. The specific data I need is an array of objects (306 objects). Every object has a property called matchday with a numeric value. I want to group all the objects that share the same property and store them in an array. What I need in the end is an array of array of objects.
Example array of objects:
[
{id: 264796, matchday: 1, …},
{id: 264797, matchday: 1, …},
{id: 264798, matchday: 2, …},
{id: 264800, matchday: 2, …},
]
What I want looks like this:
[
[{id: 264796, matchday: 1, …},{id: 264797, matchday: 1, …}],
[{id: 264798, matchday: 2, …},{id: 264800, matchday: 2, …}],
]
You can use .reduce() with Object.values() to get the desired output:
const data = [
{id: 264796, matchday: 1}, {id: 264797, matchday: 1},
{id: 264798, matchday: 2}, {id: 264800, matchday: 2}
];
const result = Object.values(
data.reduce((r, c) => {
r[c.matchday] = r[c.matchday] || [];
r[c.matchday].push(c);
return r;
}, {})
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
we can use reduce
const arr = [
{id: 264796, matchday: 1},
{id: 264797, matchday: 1},
{id: 264798, matchday: 2},
{id: 264800, matchday: 2},
]
const result = arr.reduce((acc, item) => {
if (!acc.find(accSubArr => accSubArr.find(accSubArrItem => accSubArrItem.matchday === item.matchday))) {
acc.push(arr.filter(arrItem => arrItem.matchday === item.matchday))
}
return acc;
}, [])
console.log(result)
You can try this:
const data = [{
id: 264796,
matchday: 1
},
{
id: 264797,
matchday: 1
},
{
id: 264798,
matchday: 2
},
{
id: 264800,
matchday: 2
},
]
const group = data
.map(d => d.matchday)
.filter((v, i, c) => c.indexOf(v) === i)
.map(i => data.filter(d => d.matchday === i))
console.log(group)
To add to the existing answers, here's another way making use of Map with a predicate to determine the group-by value:
const groupBy = predicate => items =>
Array.from(items.reduce((agg, next) => {
const key = predicate(next);
return agg.set(key, [].concat(agg.get(key) || []).concat(next));
}, new Map()).values());
const data = [
{name: 'A', key: 1},
{name: 'B', key: 1},
{name: 'C', key: 2},
{name: 'D', key: 2},
{name: 'E', key: 3}
];
const grouped = groupBy(x => x.key)(data);
For the fun of it, here's a recursive version of groupBy:
const groupBy = predicate => function group([next, ...items], grouped = new Map()) {
if (!next) {
return Array.from(grouped.values())
}
const key = predicate(next);
return group(items, grouped.set(key, [...(grouped.get(key) || []), next]));
}
And what the heck, here's a more imperative approach to add to the mix:
const groupBy = predicate => items => {
const cache = {};
for(item of items) {
const key = predicate(item);
cache[key] = [].concat(cache[key]).concat(item).filter(x => x)
}
return Object.values(cache);
}

Categories