How to compress duplicate elements and get their quantity values? - javascript

I need to find the elements with the same id in the array below, add their amounts and write them in a single line.
let arr = [
{ itemId: 123, name: '0', quantity: 2 },
{ itemId: 1, name: '1', quantity: 2 },
{ itemId: 13, name: '2', quantity: 2 },
{ itemId: 13, name: '3', quantity: 2 },
{ itemId: 13, name: '4', quantity: 24 },
{ itemId: 13, name: '5', quantity: 2 },
{ itemId: 1, name: '6', quantity: 4 },
{ itemId: 1, name: '7', quantity: 2 },];
I want an output like this:
[{ itemId: 123, name: '1', quantity: 2 },
{ itemId: 1, name: '2', quantity: 6 },
{ itemId: 13, name: '6', quantity: 30 }];
And my code:
const getPureList = () => {
for (let index = 0; index < arr.length; index++) {
for (let a = index + 1; a < arr.length; a++) {
if (arr[index].itemId === arr[a].itemId) {
arr[index].quantity += arr[a].quantity;
arr.splice(a, 1);
}
}
}
return arr;
};
Thanks for your help.

By keeping the name od the first object of the group, you could take an object for grouping and take the values as result.
const
array = [{ itemId: 123, name: '0', quantity: 2 }, { itemId: 1, name: '1', quantity: 2 }, { itemId: 13, name: '2', quantity: 2 }, { itemId: 13, name: '3', quantity: 2 }, { itemId: 13, name: '4', quantity: 24 }, { itemId: 13, name: '5', quantity: 2 }, { itemId: 1, name: '6', quantity: 4 }, { itemId: 1, name: '7', quantity: 2 }],
result = Object.values(array.reduce((r, o) => {
r[o.itemId] ??= { ...o, quantity: 0 };
r[o.itemId].quantity += o.quantity;
return r;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

creating a new array from two arrays with a new attribute

I have two arrays. First array is an array of object with each object respresenting a vote for an item, the id represents the item that was voted.
The second array contains all the options for that poll.
I want to create a new array with each option from the poll options with a new attribute having the percentage of votes they got from the votes array.
This is the votes array.
votes = [{
vote_id: 1, person: {name: ‘alan’}
}, {
vote_id: 2, person: {name: ‘John’}
},{
vote_id: 1, person: {name: ‘khan’}
}, {
vote_id: 1, person: {name: ‘martin’}
},{
vote_id: 3, person: {name: ‘mike’}
}]
Options = [{
id: 1, title: ’sweet’}, {
id: 2: ’salty’}, {
id: 3, title: ’spicy’}, {
id: 4, title: ’bitter’}]
This is the new array that I want to create from the data available from the above two arrays
new array = [{
Id: 1, title: ’sugar’, percentage: 60%},
{Id: 2, title: ’salt’, percentage: 20% },
{id: 3, title: ’spice’, percentage: 20%},
{id: 4, title: ‘bitter’, percentage: 0%}]
Separate the problem into two parts:
get the counts,
map percentage.
const
votes = [{ vote_id: 1, person: { name: 'alan' } }, { vote_id: 2, person: { name: 'John' } }, { vote_id: 1, person: { name: 'khan' } }, { vote_id: 1, person: { name: 'martin' } }, { vote_id: 3, person: { name: 'mike' } }],
options = [{ id: 1, title: 'sweet' }, { id: 2, title: 'salty' }, { id: 3, title: 'spicy' }, { id: 4, title: 'bitter' }],
counts = votes.reduce((r, { vote_id }) => {
r[vote_id] = (r[vote_id] || 0) + 1;
return r;
}, {}),
result = options.map(o => ({ ...o, percentage: ((counts[o.id] || 0) * 100 / votes.length).toString() + ' %' }));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to duplicate an object in an array by given quantity, ES6 and above

I'm trying to convert an array of objects where i return duplicated objects if the object properties quantity is greater than 1.
const objects = [
{ id: 1, name: "Scissor", price: 2, quantity: 3 },
{ id: 2, name: "Hat", price: 6.5, quantity: 1 },
{ id: 3, name: "Socks", price: 0.5, quantity: 5 },
];
// desired return
[
{ id: 1, name: "Scissor", price: 2 }
{ id: 1, name: "Scissor", price: 2 }
{ id: 1, name: "Scissor", price: 2 }
{ id: 2, name: "Hat", price: 6.5}
{ id: 3, name: "Socks", price: 0.5 }
{ id: 3, name: "Socks", price: 0.5 }
{ id: 3, name: "Socks", price: 0.5 }
{ id: 3, name: "Socks", price: 0.5 }
{ id: 3, name: "Socks", price: 0.5 }
]
My code:
const objects = [
{ id: 1, name: "Scissor", price: 2, quantity: 3 },
{ id: 2, name: "Hat", price: 6.5, quantity: 1 },
{ id: 3, name: "Socks", price: 0.5, quantity: 5 },
];
let newObjects= [];
Object.entries(objects).forEach(([key, value]) => {
for (let i=0; i < value.quantity; i++){
newObjects.push({ id: value.id, name: value.name, price: value.price})
}
});
console.log(newObjects);
So my code above does work, does return what i wanted, however i feel like there is a better/smoother and more of ES6 and beyond method. Could anyone please suggest a better way?
You could use .fill() and .flatMap().
const objects = [
{ id: 1, name: "Scissor", price: 2, quantity: 3 },
{ id: 2, name: "Hat", price: 6.5, quantity: 1 },
{ id: 3, name: "Socks", price: 0.5, quantity: 5 },
];
let newObjects = objects.flatMap(e=>
Array(e.quantity).fill({id: e.id, name: e.name, price: e.price})
);
console.log(newObjects);
You can use an array reduce along with an array fill.
The map is required only if you want to have unique references otherwise you can fill using the same object.
const objects = [
{ id: 1, name: "Scissor", price: 2, quantity: 3 },
{ id: 2, name: "Hat", price: 6.5, quantity: 1 },
{ id: 3, name: "Socks", price: 0.5, quantity: 5 },
];
const output = objects.reduce((a, c) => {
return a.concat(Array(c.quantity).fill({}).map(x=>({
id: c.id,
name: c.name,
price: c.price
})))
}, []);
console.log(output)

get name of object in array when option.amount equals zero

I'm trying to get an array of names of objects that have options.amount all equals to zero. Thanks for your time. This is what i tryed:
let variants = [
{
name: 'extra',
options: [
{
name: 'meat',
price: 3,
amount: 0
},
{
name: 'cheese',
price: 1,
amount: 0
}
]
},
{
name: 'sauce',
options: [
{
name: 'ketchup',
price: 2,
amount: 1
},
{
name: 'mayo',
price: 1,
amount: 0
}
]
}
];
//Expected output = ['extra']
let arrayOfOptionsNames = variants.map(x => x.options.filter(y => y.amount === 0 ? x.name : 0))
console.log(arrayOfOptionsNames)
You could use Array.prototype.filter() and Array.prototype.every() method to get your result. Every method test if every elements of the array pass the test by the given callback function and returns a boolean value.
const variants = [
{
name: 'extra',
options: [
{
name: 'meat',
price: 3,
amount: 0,
},
{
name: 'cheese',
price: 1,
amount: 0,
},
],
},
{
name: 'sauce',
options: [
{
name: 'ketchup',
price: 2,
amount: 1,
},
{
name: 'mayo',
price: 1,
amount: 0,
},
],
},
];
const ret = variants
.filter((x) => x.options.every((y) => y.amount === 0))
.map((x) => x.name);
console.log(ret);
You could filter and get the wanted property.
let variants = [{ name: 'extra', options: [{ name: 'meat', price: 3, amount: 0 }, { name: 'cheese', price: 1, amount: 0 }] }, { name: 'sauce', options: [{ name: 'ketchup', price: 2, amount: 1 }, { name: 'mayo', price: 1, amount: 0 }] }],
result = variants
.filter(({ options }) => options.every(({ amount }) => !amount))
.map(({ name }) => name);
console.log(result);

How to replace the object with the new object using javascript or lodash?

i have the datastructure like below,
const data = {
getSomething: {
id: '1',
items: [
{
id: '1',
orders: [
{
id: '1',
name: 'one1',
}
],
subItems: [
{ id: '1', name: 'subitem1' },
{ id: '2', name: 'subitem2' },
],
},
{
id: '2',
orders: [
{
id: '2',
name: 'two1',
}
],
subItems: [
{ id: '2', name: 'subitem1' },
{ id: '3', name: 'subitem2' },
],
}
],
}
}
now i have another data like below,
const item1 = {
id: '2',
orders: [
{
id: '3',
name: 'one1',
}
],
}
i have to replace the item with id 1 in data with the item1 above. how can i do it using lodash. or any other way that i can do it easily.
could someone help me with this. thanks.
const data = {
getSomething: {
id: '1',
items: [{
id: '1',
orders: [{
id: '1',
name: 'one1',
}],
subItems: [{
id: '1',
name: 'subitem1'
},
{
id: '2',
name: 'subitem2'
},
],
},
{
id: '2',
orders: [{
id: '2',
name: 'two1',
}],
subItems: [{
id: '2',
name: 'subitem1'
},
{
id: '3',
name: 'subitem2'
},
],
}
],
}
}
const item1 = {
id: '2',
orders: [{
id: '3',
name: 'one1',
}],
}
Object.assign(data.getSomething.items.find(item => item.id === item1.id),item1);
console.log(data);
Are you looking something like this ?
const data = {
getSomething: {
id: '1',
items: [
{
id: '1',
orders: [
{
id: '1',
name: 'one1',
}
],
subItems: [
{ id: '1', name: 'subitem1' },
{ id: '2', name: 'subitem2' },
],
},
{
id: '2',
orders: [
{
id: '2',
name: 'two1',
}
],
subItems: [
{ id: '2', name: 'subitem1' },
{ id: '3', name: 'subitem2' },
],
}
],
}
}
const item1 = {
id: '2',
orders: [
{
id: '3',
name: 'one1.......',
}
],
subItems: [
{ id: '2', name: 'subitem1....' },
{ id: '3', name: 'subitem2....' },
],
}
let result = data.getSomething.items.map(item=> item.id===item1.id ? ({...item1}): item);
console.log('-----Original----', data.getSomething.items);
console.log('-----Updated-----', result);
This will overwrite item with id 1 in data with the item1:
const data = {
getSomething: {
id: '1',
items: [
{
id: '1',
orders: [
{
id: '1',
name: 'one1',
}
],
subItems: [
{ id: '1', name: 'subitem1' },
{ id: '2', name: 'subitem2' },
],
},
{
id: '2',
orders: [
{
id: '2',
name: 'two1',
}
],
subItems: [
{ id: '2', name: 'subitem1' },
{ id: '3', name: 'subitem2' },
],
}
],
}
}
const item1 = {
id: '2',
orders: [
{
id: '3',
name: 'one1',
}
],
}
const oldItem = data.getSomething.items.find(item => item.id == 1);
Object.assign(oldItem, item1);
console.log(data);

compare two arrays and remove object by object id javascript

my tried code is :
const data1 = [{ id: 1, name: 'dd' }, { id: 2, name: 'dd' }, { id: 3, name: 'dd' }, { id: 4, name: 'dd' }, { id: 5, name: 'dd' }];
const sasas = [];
const data2 = [{ id: 2, name: 'dd' },{ id: 4, name: 'dd' }, { id: 5, name: 'dd' }];
data2.map((io) => {
sasas.push(io.id);
});
sasas.forEach((ik) => {
for (let i = 0; i < data1.length - 1; i++) {
if (data1[i].id === ik) {
data1.splice(i, 1);
}
}
});
console.log(data1);
i have two arrays and i map the data2 data and getting id values into sasas.
then forEach the sasas data ,
and use forloop to splice the index data of the data1.
then getting the answer is id :1 , id:3, id:5 objects in data1.
but my expected out put is :
const data1 = [{ id: 1, name: 'dd' },{ id: 3, name: 'dd' }];
please help me !
Try this
data1.filter(x=> !data2.some(y=> y.id==x.id ))
const data1 = [{ id: 1, name: 'dd' }, { id: 2, name: 'dd' }, { id: 3, name: 'dd' }, { id: 4, name: 'dd' }, { id: 5, name: 'dd' }];
const data2 = [{ id: 2, name: 'dd' },{ id: 4, name: 'dd' }, { id: 5, name: 'dd' }];
let result = data1.filter(x=>!data2.some(y=>y.id==x.id))
console.log(result);
Above short solution time complexity is O(n*m), below O(n+m) version (n,m are arrays lengths):
let h = {}; data2.map(x=>h[x.id]=1);
let result = data1.filter(x=>!h[x.id]);
const data1 = [{ id: 1, name: 'dd' }, { id: 2, name: 'dd' }, { id: 3, name: 'dd' }, { id: 4, name: 'dd' }, { id: 5, name: 'dd' }];
const data2 = [{ id: 2, name: 'dd' },{ id: 4, name: 'dd' }, { id: 5, name: 'dd' }];
let h = {}; data2.map(x=>h[x.id]=1); // we use hash map with data2 ids
let result = data1.filter(x=>!h[x.id]);
console.log(result);
You can try following 2 approaches. Also, in place of creating an Array you can use Set (better performance)
Update existing array using while loop
const data1 = [{ id: 1, name: 'dd' }, { id: 2, name: 'dd' }, { id: 3, name: 'dd' }, { id: 4, name: 'dd' }, { id: 5, name: 'dd' }];
const data2 = [{ id: 2, name: 'dd' },{ id: 4, name: 'dd' }, { id: 5, name: 'dd' }];
const sasas = data2.reduce((a,{id}) => a.add(id), new Set())
let i = 0;
while(i < data1.length) {
if(sasas.has(data1[i].id)) {
data1.splice(i,1);
} else i++;
}
console.log(data1);
Create new array using Array.filter
const data1 = [{ id: 1, name: 'dd' }, { id: 2, name: 'dd' }, { id: 3, name: 'dd' }, { id: 4, name: 'dd' }, { id: 5, name: 'dd' }];
const data2 = [{ id: 2, name: 'dd' },{ id: 4, name: 'dd' }, { id: 5, name: 'dd' }];
const sasas = data2.reduce((a,{id}) => a.add(id), new Set())
const result = data1.filter(({id}) => !sasas.has(id));
console.log(result);
First of all, you could use that map better, instead of
data2.map((io) => {
sasas.push(io.id);
});
you could simply:
sasas = data2.map(io => io.id);
Your error:
for (let i = 0; i < data1.length - 1; i++) {
That means you never check the last index of the array, you can either change the < to a <= or simply remove the -1.
This should work:
for (let i = 0; i < data1.length; i++) {
Array.filter
The functionality you are trying to achieve is easily obtainable via .filter() function, like this:
const data1 = [{ id: 1, name: 'dd' }, { id: 2, name: 'dd' }, { id: 3, name: 'dd' }, { id: 4, name: 'dd' }, { id: 5, name: 'dd' }];
const data2 = [{ id: 2, name: 'dd' },{ id: 4, name: 'dd' }, { id: 5, name: 'dd' }];
const sasas = data2.map((io) => io.id);
var result = data1.filter(e => sasas.indexOf(e.id) === -1)
console.log(result);
Because of this loop, i is stopped at data1.length - 2
for (let i = 0; i < data1.length - 1; i++) {
Variable i should be from 0 to data1.length - 1, which makes the condition become
i < data1.length

Categories

Resources