I have array object obj how to move particular key value store inside another array items in javascript.
I would like to know how to pass particular key value inside another array in javascript
var obj = [
{
id:1,
store: "10",
items: [{name:"sample1", total: 20}, {name:"sample2", total: 10}] // add store
},
{
id:1,
store: "11",
items: [{name:"sample3", total: 10}, {name:"sample4", total: 10}] // add store
}
]
function newarray(obj){
return obj.map(e=>...e,e.items.map(i=>{...i,store: e.store })
}
Expected Output
[
{
id:1,
store: "10",
items: [{name:"sample1", total: 20, store: "10"}, {name:"sample2", total: 10, store: "10"}]
},
{
id:1,
store: "11",
items: [{name:"sample3", total: 10, store: "11"}, {name:"sample4", total: 10, store: "11"}]
}
]
You are almost in the right direction, just few changes need to be done in your map function to get expected output:
var obj = [ { id:1, store: "10", items: [{name:"sample1", total: 20}, {name:"sample2", total: 10}] }, { id:1, store: "11", items: [{name:"sample3", total: 10}, {name:"sample4", total: 10}] }];
var result = obj.map(val=>(val.items = val.items.map(p=>({...p,store:val.store})), val));
console.log(result);
You can use reduce and forech if you want to try a different approach
var obj = [
{
id:1,
store: "10",
items: [{name:"sample1", total: 20}, {name:"sample2", total: 10}]
},
{
id:1,
store: "11",
items: [{name:"sample3", total: 10}, {name:"sample4", total: 10}]
}
]
newob=obj.reduce((acc,curr)=>{
curr.items.forEach(x=>{
x.store=curr.store
})
return [...acc,{...curr}]
},[])
console.log(newob)
Related
I'm a beginner at webdev and I'm having a little problem with reactjs. I have an array of data about universities, like:
const data = [
{
name: "UFSM",
total: 17,
filled: 12,
approved: 10,
reproved: 1,
dropouts: 1,
requests: 170,
approved_requests: 120,
disciplines: [{name: "engineering", value: 10}, {name:"biology", value: 20}, ...]
},
{...
disciplines: [{name: "engineering", value: 7}, ....]
},...]
I'm using the map function to map all their names into an array, like:
let data_name = props.data.map((data) => data.name);
Is it possible to use map to group into an array the value of disciplines with the same name from different universities? Having an output like:
data_engineering = ["10", "7", ...]
So that I could have all engineering related disciplines from different universities on the same array.
const data = [{
name: "UFSM",
total: 17,
filled: 12,
approved: 10,
reproved: 1,
dropouts: 1,
requests: 170,
approved_requests: 120,
disciplines: [{
name: "engineering",
value: 10
}, {
name: "biology",
value: 20
}]
}, {
name: "ABCD",
total: 17,
filled: 12,
approved: 10,
reproved: 1,
dropouts: 1,
requests: 170,
approved_requests: 120,
disciplines: [{
name: "engineering",
value: 4
}, {
name: "biology",
value: 5
}]
}, {
name: "EFGH",
total: 17,
filled: 12,
approved: 10,
reproved: 1,
dropouts: 1,
requests: 170,
approved_requests: 120,
disciplines: [{
name: "engineering",
value: 5
}, {
name: "biology",
value: 9
}]
}]
let result = {};
data.map((data) => data.disciplines).forEach((item, index) => {
item.forEach((item, index) => {
if (!result[item.name]) {
result[item.name] = []
}
result[item.name].push(item.value);
});
});
console.log(JSON.stringify(result));
If you want an array for a single discipline like engineering, you can do the following map:
data_engineering =
props.data.map((uni) => uni.disciplines.engineering);
This array will have an undefined value for a university that doesn't have an engineering value defined. But that is probably what you want, because it means the indices line up with the indices of data_name.
If you want to build such an array for all disciplines, you can do the following:
const dataDiscipline = {};
// 1. Collect all disciplines from all universities
// by making them a key of dataDiscipline.
props.data.forEach((uni) =>
uni.disciplines.forEach((discipline) =>
dataDiscipline[discipline] = null
)
);
// 2. Now build the discipline array for each discipline.
Object.keys(dataDiscipline).forEach((discipline) =>
dataDiscipline[discipline] =
props.data.map((uni) => uni.disciplines[discipline])
);
// You can now use e.g. dataDiscipline.engineering
I am using JS and LoDash library.
Data that I receive from the server looks like this :
const statsToSort = [
{name: "critA", value: 11111},
{name: "critA", value: 11},
{name: "critA", value: 221},
{name: "critA", value: 54},
{name: "critB", value: 1222},
{name: "critC", value: 231},
{name: "critD", value: 323},
{name: "critC", value: 0},
]
I Need to rearrange it, summ the values for the same keys and reOrganise it. For this I created the following array:
let finalStats = [{ "critA": 0 }, { "critB": 0 }, { "critC": 0 }, { "CritD": 0 }];
I am trying to use the Lodash library to fill the finalStats jumping of the name and summing the values.
The function I have so far is like this:
function mergeNames(arr) {
return _.chain(arr).groupBy('name').mapValues(function (v) {
return _.sum(v);
})
The expected result is supposed to be like this:
/**
statsToSort:[
{name: "critA", value:11397},
{name: "critB", value:1222},
{name: "critC", value:231},
{name: "critD", value:323},
*/
So far my function that I have shown does ...Nothing. Like, at all. It does not even sort the array by keys.
Question:
Can you help me
modify the function to get the result I mentioned
maybe add another layer to the function so that it would do the populating of the finalStats array considering that the names might not be alphabetically arranged and statsToSort might not contain one or few names that are to be populated in the finalStats.
Thanks in advance
You could take a map and get the summed values.
const
statsToSort = [{ name: "critA", value: 11111 }, { name: "critA", value: 11 }, { name: "critA", value: 221 }, { name: "critA", value: 54 }, { name: "critB", value: 1222 }, { name: "critC", value: 231 }, { name: "critD", value: 323 }, { name: "critC", value: 0 }],
result = Array
.from(
statsToSort.reduce((m, { name, value }) => m.set(name, (m.get(name) || 0) + value), new Map),
([name, value]) => ({ name, value })
)
.sort((a, b) => a.name.localeCompare(b.name));
console.log(result);
This appears to do what you're after:
const statsToSort = [
{name: "critA", value: 11111},
{name: "critA", value: 11},
{name: "critA", value: 221},
{name: "critA", value: 54},
{name: "critB", value: 1222},
{name: "critC", value: 231},
{name: "critD", value: 323},
{name: "critC", value: 0},
]
let mergeNames = arr => _(arr)
.groupBy('name')
.mapValues(vals => ({
name: vals[0].name,
value: _.sumBy(vals, 'value')
}))
.value()
let finalStats = mergeNames(statsToSort)
console.log(finalStats)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
if i want for an example loop Through this Array to find specific item in Items Array how to approach that? i made this logic but it doesn't work
DATA.map((D)=>{
return D.items.find((item)=>{
return item.name ==='Blue Beanie'
})
})
this is the Array plus how to create new ONE array includes the both of items arrays to be like that: items: [{
id: 1,
name: 'Brown Brim',
price: 25
},
{
id: 2,
name: 'Blue Beanie',
price: 18
},
{
id: 3,
name: 'Adidas NMD',
price: 220
},
{
id: 4,
name: 'Adidas Yeezy',
price: 280
}
]
const DATA= [
{
id: 1,
title: 'Hats',
routeName: 'hats',
items: [
{
id: 1,
name: 'Brown Brim',
price: 25
},
{
id: 2,
name: 'Blue Beanie',
price: 18
}
]
},
{
id: 2,
title: 'Sneakers',
routeName: 'sneakers',
items: [
{
id: 3,
name: 'Adidas NMD',
price: 220
},
{
id: 4,
name: 'Adidas Yeezy',
price: 280
}
]
}
];
Transform DATA into list of items and find from that list your expected item
const res = DATA.flatMap((D) => D.items).find(
(item) => item.name === "Brown Brim"
)
const DATA = [
{
id: 1,
title: "Hats",
routeName: "hats",
items: [
{
id: 1,
name: "Brown Brim",
price: 25,
},
{
id: 2,
name: "Blue Beanie",
price: 18,
},
],
},
{
id: 2,
title: "Sneakers",
routeName: "sneakers",
items: [
{
id: 3,
name: "Adidas NMD",
price: 220,
},
{
id: 4,
name: "Adidas Yeezy",
price: 280,
},
],
},
]
const res = DATA.flatMap((D) => D.items).find(
(item) => item.name === "Brown Brim"
)
console.log(res)
Reference
Array.prototype.flatMap()
Maybe this is helpful?
const DATA= [
{id: 1,title:'Hats',routeName:'hats',
items:[{id: 1,name:"Brown Brim",price:25},
{id: 2,name: 'Blue Beanie',price: 18}]},
{id: 2,title: 'Sneakers',routeName: 'sneakers',
items: [{id: 3,name: 'Adidas NMD',price: 220},
{id: 4,name: 'Adidas Yeezy',price: 280}]}
];
console.log(DATA.map(D=>D.items.find(item=>item.name==='Brown Brim'))
.filter(e=>e))
The .map returns either an element matching your criterion or undefined, The chained .filter then removes all "falsy" elements, i. e. all the undefined ones.
As for the first question "loop Through this Array to find a specific item in Items Array"
given it is not sorted in any way, this can be done by iterating over the DATA array and search inside the items
If want to have access to the item from the outside of the 'forEach' scope you have to declare the variable outside
Regarding the second question, use the reduce function while iterating the array
NOTE: You can obviously combine both tasks as you already iterate through the array, so no need to do it twice. But to avoid confusion, I separated the logic.
Also, if you do choose to combine the tasks, using the reduce is not relevant, but very much like the answer to the first question, you can declare a buffer such as an array, and just copy items to it on the go (I'll leave out questions on performance for that matter)
const DATA = [
{
id: 1, title: 'Hats', routeName: 'hats',
items: [
{id: 1,name: 'Brown Brim',price: 25},
{id: 2,name: 'Blue Beanie',price: 18}
]
},
{
id: 2, title: 'Sneakers', routeName: 'sneakers',
items: [
{id: 3,name: 'Adidas NMD',price: 220},
{id: 4,name: 'Adidas Yeezy',price: 280}
]
}
];
//Question 1
//creating the object that will hold the item
//outside of the 'forEach' scope so we can use it later
let res = {};
const searchRes = DATA.forEach(entry => {
entry.items.forEach(item => {
if (item.name === 'Brown Brim')
//duplicating the item to a variable declared outside of this scope
res = { ...item
};
});
});
console.log(`Q1 - The item we found:`);
console.log(res);
// Question 2
// Merging all object inside the 'items' array using Reduce
const merged = DATA.reduce((acc, curr) =>
acc.concat(curr.items), []);
console.log(`Q2 - The merged array:`);
console.log(merged)
How do you groupBy array of objects based on specific properties in vanilla javascript? For example this given:
const products = [
{
category: "Sporting Goods",
price: "$49.99",
stocked: true,
name: "Football"
},
{
category: "Sporting Goods",
price: "$9.99",
stocked: true,
name: "Baseball"
},
{
category: "Sporting Goods",
price: "$29.99",
stocked: false,
name: "Basketball"
},
{
category: "Electronics",
price: "$99.99",
stocked: true,
name: "iPod Touch"
},
{
category: "Electronics",
price: "$399.99",
stocked: false,
name: "iPhone 5"
},
{ category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7" }
];
i want to run a reduce function that would result to a new array of objects like this:
Intended Output:
const categorize = [
{
category:"Sporting Goods",
products: [
{
name:"Football",
price: "$49.99",
stocked: true
},
{
name:"Baseball",
price: "$9.99",
stocked: true
},
{
name:"Basketball",
price: "$29.99",
stocked: true
}
]
},
{
category: "Electronics",
products: [
{
name: "iPod Touch",
price: "$99.99",
stocked: true
},
{
name: "iPhone 5",
price: "$399.99",
stocked: false
},
{
name: "Nexus 7",
price: "$199.99",
stocked: true
}
]
}
]
i based my solution from the tutorial here: https://www.consolelog.io/group-by-in-javascript/ using the reduce function.
Here's my code:
const groupBy = (arr,prop)=>{
return arr.reduce((groups,item)=>{
let val = item[prop];
groups[val] = groups[val]||[];
groups[val].push(item);
return groups
},{});
}
const categorize = groupBy(products,'category');
console.log(categorize);
/* returns an Object like
Object {Sporting Goods: Array[3], Electronics: Array[3]}
however it's not the intended output.
*/
I tried to return Object.values(obj) or Object.entries(obj) inside the groupBy function but it just returns an array of 2 arrays like [Array[3],Array[3]] and if i set the initial value (2nd parameter of reduce) to empty [] instead of {}, the output is just an empty array. Need help, thanks!
Because you want an array containing objects (rather than just an array of plain values), create a { category, products: [] } object if it doesn't exist in the accumulator:
const products=[{category:"Sporting Goods",price:"$49.99",stocked:!0,name:"Football"},{category:"Sporting Goods",price:"$9.99",stocked:!0,name:"Baseball"},{category:"Sporting Goods",price:"$29.99",stocked:!1,name:"Basketball"},{category:"Electronics",price:"$99.99",stocked:!0,name:"iPod Touch"},{category:"Electronics",price:"$399.99",stocked:!1,name:"iPhone 5"},{category:"Electronics",price:"$199.99",stocked:!0,name:"Nexus 7"}];
const output = Object.values(
products.reduce((a, { category, ...item }) => {
if (!a[category]) {
a[category] = { category, products: [] };
}
a[category].products.push(item);
return a;
}, {})
);
console.log(output);
function (){
var map = {};
products.forEach((p) => {
if (map[p.category]) {
var c = p.category;
delete p.category;
map[c].push(p);
} else {
var c = p.category;
delete p.category;
map[c]=[c]
}
});
Object.keys(map).forEach((m) => {
ans.push({category:m, products: map[m]})
})
}
you can collect in one go products and map them.
Then make your resultinng array
I am running this accumulator, it works great but I find it challenging to add some proprities in the same object :
let expenseCategories = expenseObj.reduce((acc, obj) => {
let category = obj['category'];
// let amount = obj['amount'];
if (category in acc) {
acc[category] += 1;
} else {
acc[category] = 1;
}
return acc;
}, {});
{Transportation: 2, Food: 1, Clothes: 1, Bills: 2, Fun: 1, …}
My initial object also contains a transaction amount
{amount: 10, category: "Transportation", date: 20190510, expense: true, ...
{amount: 20, category: "Drinks", date: 20190510, expense: true, ...
{amount: 30, category: "Bills", date: 20190510, expense: true, ...
{amount: 40, category: "Bills", date: 20190510, expense: true, ...
My goal here is to calculate sum of each categories like bills in the example above would be 70.
I am looking to add this info to display some chart, the expected array looks something like that :
0: {name: "Transportation", value: 2, total: 123}
1: {name: "Food", value: 1, total: 456}
2: {name: "Clothes", value: 1, total: 789}
This is my attempt with the correct data I already have:
let outExpense = Object.entries(expenseCategories).map(([name, value]) => ({ name, value }));
This should be dynamic because I don't know categories prior to running code. These are user inputs. Please advise. Thanks
You are counting the occurrences of each category. You need to change your implementation a little bit. Instead of creating a number as value, you can create the object you need in the output array as value. Then, simply use Object.values() on the accumulator object to get the array of grouped values
const expenseObj = [{amount: 10, category: "Transportation", date: 20190510, expense: true},
{amount: 20, category: "Drinks", date: 20190510, expense: true},
{amount: 30, category: "Bills", date: 20190510, expense: true},
{amount: 40, category: "Bills", date: 20190510, expense: true}]
let groupCategories = expenseObj.reduce((acc, obj) => {
let { category, amount } = obj;
if (category in acc) {
acc[category].value++;
acc[category].total += amount;
} else {
acc[category] = { name: category, value: 1, total: amount };
}
return acc;
}, {});
console.log(Object.values(groupCategories))
This is how the accumulator would look like after the changes. If the current object's category already exists in the accumulator, increment the value and total. Else, add the category as key and a new object as it's value
{
"Transportation": {
"name": "Transportation",
"value": 1,
"total": 10
},
"Drinks": {
"name": "Drinks",
"value": 1,
"total": 20
},
"Bills": {
"name": "Bills",
"value": 2,
"total": 70
}
}