Related
How can I get the result from arr1 and arr2, When the ID matches I need to copy the content from arr1
const arr1 = [
{ id: 1, name: "omar" },
{ id: 2, name: "laith" },
{ id: 3, name: "aref" },
]
const arr2 = [
{ id: 1, rating: "good" },
{ id: 2, rating: "very good" },
{ id: 2, rating: "very good" },
{ id: 3, rating: "Excellence" },
{ id: 3, rating: "Excellence" },
]
//expected output
const result = [
{ id: 1, rating: "good", name: "omar" },
{ id: 1, rating: "good", name: "omar" },
{ id: 2, rating: "very good", name: "laith" },
{ id: 3, rating: "Excellence", name: "aref" },
{ id: 3, rating: "Excellence", name: "aref" },
]
use reduce with filter
const arr1 = [ { id: 1, name: "omar" }, { id: 2, name: "laith" }, { id: 3, name: "aref" }, ];
const arr2 = [ { id: 1, rating: "good" }, { id: 2, rating: "very good" }, { id: 2, rating: "very good" }, { id: 3, rating: "Excellence" }, { id: 3, rating: "Excellence" }, ];
const result = arr1.reduce((acc,item) => {
const list = arr2.filter(i => i.id === item.id)
return [...acc, ...list.map(i => ({id: i.id,rating:i.rating, name: item.name}))]
}, [])
console.log(result)
Basically with a loop. Actually 2. Using a temporary object (result) as dictionary (or map) we can make it efficient searching for a match to each id. This is of complexity O(n) basically.
const arr1 = [ { id: 1, name: "omar" }, { id: 2, name: "laith" }, { id: 3, name: "aref" }, ];
const arr2 = [ { id: 1, rating: "good" }, { id: 2, rating: "very good" }, { id: 2, rating: "very good" }, { id: 3, rating: "Excellence" }, { id: 3, rating: "Excellence" }, ];
var result = {}
arr1.forEach(function(item1) {
result[item1.id] = item1;
});
arr2.forEach(function(item2) {
result[item2.id] = (result[item2.id] || item2)
result[item2.id]['rating'] = item2.rating
})
result = Object.values(result)
console.log(result)
I am trying pushing the name but in the console log I see just a number and not the actual name
What am i doing wrong??
const cartItems = [{
id: 1,
name: "Soup",
price: 3,
category: "starters",
count: 1
},
{
id: 2,
name: "Pâté",
price: 5,
category: "starters",
count: 1
},
{
id: 9,
name: "Sticky toffee",
price: 18,
category: "desserts",
count: 1
}
]
var dishesArray = [];
var groupByCategory = []
cartItems.reduce(function(res, value) {
if (!res[value.category]) {
res[value.category] = {
category: value.category,
count: 0,
dishes: dishesArray.push(value.name), // problem here
};
groupByCategory.push(res[value.category]);
}
res[value.category].count += value.count;
return res;
}, {});
console.log(groupByCategory)
Expected output
[{category: "starters", count: 2, dishes:["Soup","Pâté"]},
{category: "desserts", count: 1, dishes:["Sticky toffee"]}]
As mentioned, a push returns an int
I believe you are looking for this much shortened reduce
const cartItems = [
{ id: 1, name: "Soup", price: 3, category: "starters", count: 1 },
{ id: 2, name: "Pâté", price: 5, category: "starters", count: 1 },
{ id: 9, name: "Sticky toffee", price: 18, category: "desserts", count: 1}
];
const groupByCategory = cartItems.reduce(function(res, value) {
const cat = value.category;
res[cat] = res[cat] || { category: cat, count: 0, dishes: [] };
res[cat].count += value.count;
res[cat].dishes.push(value.name)
return res;
}, {});
console.log(groupByCategory)
I have the object arrays like below:
const obj = {
top: [
{ id: 1, name: "Spider-man", rating: 1 },
{ id: 2, name: "Iron man", rating: 3 },
{ id: 3, name: "Hulk", rating: 5 }
],
middle: [
{ id: 1, name: "Spider-man", rating: 4.5 },
{ id: 2, name: "Iron man", rating: 3.5 },
{ id: 3, name: "Hulk", rating: 1.5 }
],
bottom: [
{ id: 1, name: "Spider-man", rating: 5 },
{ id: 2, name: "Iron man", rating: 2 },
{ id: 3, name: "Hulk", rating: 4 }
]
};
And what I want is to group by id, name and list out rating belonging its like below
const users = [
{
id: 1,
name: "Spider-man",
rating: {top: 1, middle: 4.5, bottom: 5}
},
{
id: 2,
name: "Iron man",
rating: {top: 3, middle: 3.5, bottom: 2}
},
{
id: 3,
name: "Hulk",
rating: {top: 5, middle: 1.5, bottom: 4}
}
];
I've tried this approach but seems it can achieve in more ways such as .reduce, for...of with more elegant, right?
const obj = {
top: [
{ id: 1, name: "Spider-man", rating: 1 },
{ id: 2, name: "Iron man", rating: 3 },
{ id: 3, name: "Hulk", rating: 5 }
],
middle: [
{ id: 1, name: "Spider-man", rating: 4.5 },
{ id: 2, name: "Iron man", rating: 3.5 },
{ id: 3, name: "Hulk", rating: 1.5 }
],
bottom: [
{ id: 1, name: "Spider-man", rating: 5 },
{ id: 2, name: "Iron man", rating: 2 },
{ id: 3, name: "Hulk", rating: 4 }
]
};
var result = obj.top.map(x => ({
id: x.id,
name: x.name,
rating: {
top: obj.top.find(t => t.id === x.id).rating,
middle: obj.middle.find(t => t.id === x.id).rating,
bottom: obj.bottom.find(t => t.id === x.id).rating,
}
}));
console.log(result);
Any other ways to achieve it? Thanks in advance.
You need to map one of the subarrays to find each character's rating, so I think your current approach is pretty reasonable. You can make it a bit less repetitive by making an array of the properties (top, middle, bot) beforehand, then iterating over them instead of listing each different one:
const obj = {
top: [
{ id: 1, name: "Spider-man", rating: 1 },
{ id: 2, name: "Iron man", rating: 3 },
{ id: 3, name: "Hulk", rating: 5 }
],
middle: [
{ id: 1, name: "Spider-man", rating: 4.5 },
{ id: 2, name: "Iron man", rating: 3.5 },
{ id: 3, name: "Hulk", rating: 1.5 }
],
bottom: [
{ id: 1, name: "Spider-man", rating: 5 },
{ id: 2, name: "Iron man", rating: 2 },
{ id: 3, name: "Hulk", rating: 4 }
]
};
const props = ['top', 'middle', 'bottom'];
var result = obj.top.map(x => ({
id: x.id,
name: x.name,
rating: Object.fromEntries(
props.map(prop =>
[prop, obj[prop].find(t => t.id === x.id).rating]
)
)
}));
console.log(result);
Another approach that's less computationally complex:
const obj = {
top: [
{ id: 1, name: "Spider-man", rating: 1 },
{ id: 2, name: "Iron man", rating: 3 },
{ id: 3, name: "Hulk", rating: 5 }
],
middle: [
{ id: 1, name: "Spider-man", rating: 4.5 },
{ id: 2, name: "Iron man", rating: 3.5 },
{ id: 3, name: "Hulk", rating: 1.5 }
],
bottom: [
{ id: 1, name: "Spider-man", rating: 5 },
{ id: 2, name: "Iron man", rating: 2 },
{ id: 3, name: "Hulk", rating: 4 }
]
};
const byName = {};
for (const [prop, arr] of Object.entries(obj)) {
for (const item of arr) {
byName[item.name] ??= { ...item, rating: {} };
byName[item.name].rating[prop] = item.rating;
}
}
console.log(Object.values(byName));
You could do it in a one-liner way
const obj = {
top: [
{ id: 1, name: "Spider-man", rating: 1 },
{ id: 2, name: "Iron man", rating: 3 },
{ id: 3, name: "Hulk", rating: 5 },
],
middle: [
{ id: 1, name: "Spider-man", rating: 4.5 },
{ id: 2, name: "Iron man", rating: 3.5 },
{ id: 3, name: "Hulk", rating: 1.5 },
],
bottom: [
{ id: 1, name: "Spider-man", rating: 5 },
{ id: 2, name: "Iron man", rating: 2 },
{ id: 3, name: "Hulk", rating: 4 },
],
};
const res = Array.from(
Object.entries(obj)
.flatMap(([rater, ratee]) =>
ratee.map(({ id, name, rating }) => ({
id,
name,
[rater]: rating,
}))
)
.reduce(
(acc, { id, ...restInfo }) =>
acc.set(id, { ...(acc.get(id) || {}), ...restInfo }),
new Map()
)
).map(([id, { name, ...rating }]) => ({ id, name, rating }));
console.log(res);
Using Dictionary along with Logical nullish assignment (??=)
The main idea includes 2 steps:
Loop all [key, values] of the object.
Inner each the values of the object, we loop to determine which the user's rating along with key belongs by user.id.
const obj = {
top: [
{ id: 1, name: "Spider-man", rating: 1 },
{ id: 2, name: "Iron man", rating: 3 },
{ id: 3, name: "Hulk", rating: 5 }
],
middle: [
{ id: 1, name: "Spider-man", rating: 4.5 },
{ id: 2, name: "Iron man", rating: 3.5 },
{ id: 3, name: "Hulk", rating: 1.5 }
],
bottom: [
{ id: 1, name: "Spider-man", rating: 5 },
{ id: 2, name: "Iron man", rating: 2 },
{ id: 3, name: "Hulk", rating: 4 }
]
};
// Refactor code: using Dictionary along with `Logical nullish assignment (??=)` .
var result = Object.entries(obj).reduce((acc, [key, values]) => {
values.forEach(v => {
acc[v.id] ??= {...v, rating: {}};
acc[v.id].rating[key] = v.rating;
});
return acc;
}, {});
console.log(Object.values(result));
/* Old versions: using Array approach
var result = Object.entries(obj).reduce((acc, [key, values]) => {
values.forEach(v => {
var x = acc.find(r => r.id === v.id);
if(x !== undefined){
x.rating[key] = v.rating;
}else{
x = { id: v.id, name: v.name, rating: {[key]: v.rating} };
acc.push(x);
}
});
return acc;
}, []);
*/
More detailed explanation:
With the dictionary approach instead of array, you can achieve it with the highest performance both time and space complexity (as #CertainPerformance's comment).
From MDN Web docs said that:
The logical nullish assignment (x ??= y) operator only assigns if x is nullish (null or undefined).
const obj = {
top: [
{ id: 1, name: "Spider-man", rating: 1 },
{ id: 2, name: "Iron man", rating: 3 },
{ id: 3, name: "Hulk", rating: 5 }
],
middle: [
{ id: 1, name: "Spider-man", rating: 4.5 },
{ id: 2, name: "Iron man", rating: 3.5 },
{ id: 3, name: "Hulk", rating: 1.5 }
],
bottom: [
{ id: 1, name: "Spider-man", rating: 5 },
{ id: 2, name: "Iron man", rating: 2 },
{ id: 3, name: "Hulk", rating: 4 }
]
};
const tempArr1 = Object.keys(obj).reduce((arr, key) => {
obj[key].forEach((item) => {
arr = [...arr, { ...item, rating: { [key]: item.rating } }];
});
return arr;
}, []);
const result = tempArr1.reduce((arr, el) => {
let tempObj = { ...el };
const index = arr.findIndex((tempItem) => tempItem.id === tempObj.id);
if (~index) {
arr[index] = {
...tempObj,
rating: {
...arr[index].rating,
...tempObj.rating
}
};
} else {
arr = [...arr, tempObj];
}
return arr;
}, []);
console.log(result);
const obj = {
top: [
{ id: 1, name: "Spider-man", rating: 1 },
{ id: 2, name: "Iron man", rating: 3 },
{ id: 3, name: "Hulk", rating: 5 }
],
middle: [
{ id: 1, name: "Spider-man", rating: 4.5 },
{ id: 2, name: "Iron man", rating: 3.5 },
{ id: 3, name: "Hulk", rating: 1.5 }
],
bottom: [
{ id: 1, name: "Spider-man", rating: 5 },
{ id: 2, name: "Iron man", rating: 2 },
{ id: 3, name: "Hulk", rating: 4 }
]
};
var result = [];
for(let [key, values] of Object.entries(obj))
for(let item of values){
let x = result.find(r => r.id === item.id);
if(x !== undefined){
x.rating[key] = item.rating;
}else{
x = { id: item.id, name: item.name, rating: {[key]: item.rating} };
result.push(x);
}
}
console.log(result);
Currently I have an array that contains my clothing (fictitious data):
myClothes = [
{
type: 'shirts',
pieces: [
{
brand: 'patagonia',
quantity: 6,
},
{
brand: 'hugo boss',
quantity: 3,
},
],
},
{
type: 'trousers',
pieces: [
{
brand: 'jack & jones',
quantity: 2,
},
{
brand: 'zara',
quantity: 4,
},
{
brand: 'versace',
quantity: 1,
},
],
},
{
type: 'socks',
pieces: [
{
brand: 'no-name',
quantity: 12,
},
],
},
];
As you see, the array contains objects (shirts, trousers, socks), that seperate the clothing by their type. Now, what can I do with javascript to make a new array of that which looks like this below here?
So where just all pieces are unseperated from shirts/trousers/socks, and it should just show how much articles I have of the brand.
allPiecesUnseperated = [
{
brand: 'patagonia',
quantity: 6,
},
{
brand: 'hugo boss',
quantity: 3,
},
{
brand: 'jack & jones',
quantity: 2,
},
{
brand: 'zara',
quantity: 4,
},
{
brand: 'versace',
quantity: 1,
},
{
brand: 'no-name',
quantity: 12,
},
];
const clothes = [{
type: 'shirts',
pieces: [{
brand: 'patagonia',
quantity: 6,
},
{
brand: 'hugo boss',
quantity: 3,
},
],
},
{
type: 'trousers',
pieces: [{
brand: 'jack & jones',
quantity: 2,
},
{
brand: 'zara',
quantity: 4,
},
{
brand: 'versace',
quantity: 1,
},
],
},
{
type: 'socks',
pieces: [{
brand: 'no-name',
quantity: 12,
}, ],
},
];
const result = clothes.map(({
pieces
}) => pieces).reduce((acc, arr) => [...acc, ...arr], []);
console.log(result);
Use .flatMap() function
const myClothes = [
{
type: 'shirts',
pieces: [
{ brand: 'patagonia', quantity: 6 },
{ brand: 'hugo boss', quantity: 3 }
]
},
{
type: 'trousers',
pieces: [
{ brand: 'jack & jones', quantity: 2 },
{ brand: 'zara', quantity: 4, },
{ brand: 'versace', quantity: 1 }
]
},
{
type: 'socks',
pieces: [
{ brand: 'no-name', quantity: 12 },
]
}
];
const output = myClothes.flatMap(o => o.pieces);
console.log(output);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Probably not the most efficient (since concat does create a new array everytime it is invoked) or the most elegant solution, but should get the job done.
var all = []
myClothes.forEach((item) => {
all = all.concat(item.pieces)
})
Hello I working in java script & having issue to sort the values and get sum by categories right now i have hotel_id and category_id.
let myarray = [
{
price: 257,
category: 1,
hotel_id: 4
},
{
price: 493,
category: 1,
hotel_id: 3
},
{
price: 514,
category: 1,
hotel_id: 3
},
{
price: 257,
category: 1,
hotel_id: 3
},
{
price: 104,
category: 1,
hotel_id: 3
},
{
price: 295,
category: 1,
hotel_id: 3
},
{
price: 125,
category: 1,
hotel_id: 2
},
{
price: 125,
category: 1,
hotel_id: 2
},
{
price: 157,
category: 1,
hotel_id: 2
},
{
price: 125,
category: 1,
hotel_id: 2
},
{
price: 125,
category: 1,
hotel_id: 1
},
{
price: 43,
category: 1,
hotel_id: 1
},
{
price: 43,
category: 2,
hotel_id: 1
},
{
price: 43,
category: 2,
hotel_id: 1
}
];
var hotel_to_values = myarray.reduce(function (obj, item) {
obj[item.hotel_id] = obj[item.hotel_id] || [];
obj[item.hotel_id].push(item.category);
return obj;
}, {});
var hotels = Object.keys(hotel_to_values).map(function (key) {
return {hotel_id: key, category: hotel_to_values[key]};
});
I need to sort or group by something like this
hotel 1
category 1
price 20
category 2
price 20 , price 30
right now my result is
[
{
"hotel_id": "1",
"category": [
1,
1,
2,
2
]
},
{
"hotel_id": "2",
"category": [
1,
1,
1,
1
]
},
{
"hotel_id": "3",
"category": [
1,
1,
1,
1,
1
]
},
{
"hotel_id": "4",
"category": [
1
]
}
]
I need prices inside the categories
I update my code now you can check what actually i am doing yes i use reduce method but can't able to get the actual result.
In your reduce() you aren't breaking out each category. I'm not 100% sure of output wanted for category , following uses an object with each unique value as key and array of prices for each category
var hotel_to_values = myarray.reduce(function(obj, item) {
const o = obj[item.hotel_id] = obj[item.hotel_id] || {};
o[item.category] = (o[item.category] || []).concat(item.price);
return obj;
}, {});
var hotels = Object.keys(hotel_to_values).map(function (key) {
return {hotel_id: key, category: hotel_to_values[key]};
});
console.log(hotels)
.as-console-wrapper {max-height: 100%!important;}
<script>
let myarray = [{
price: 257,
category: 1,
hotel_id: 4
},
{
price: 493,
category: 1,
hotel_id: 3
},
{
price: 514,
category: 1,
hotel_id: 3
},
{
price: 257,
category: 1,
hotel_id: 3
},
{
price: 104,
category: 1,
hotel_id: 3
},
{
price: 295,
category: 1,
hotel_id: 3
},
{
price: 125,
category: 1,
hotel_id: 2
},
{
price: 125,
category: 1,
hotel_id: 2
},
{
price: 157,
category: 1,
hotel_id: 2
},
{
price: 125,
category: 1,
hotel_id: 2
},
{
price: 125,
category: 1,
hotel_id: 1
},
{
price: 43,
category: 1,
hotel_id: 1
},
{
price: 43,
category: 2,
hotel_id: 1
},
{
price: 43,
category: 2,
hotel_id: 1
}
];
</script>