setting object key dynamically in javascript - javascript

I have an object like this:
let inputData = {
"dimensions": [
{
"id": "dimension_re",
"label": "Region",
"values": ["East", "East", "West", "SouthWest", "South","NorthEast"]
},
{
"id": "dimension_cnt",
"label": "County",
"values": ["London", "Italy", "Germany", "US", "Russia","India"]
},
{
"id": "measure_sales",
"label": "Sales",
"values": [100, 156, 432, 462, 25,100]
},
{
"id": "measure_qty",
"label": "Quantity",
"values": [85, 34, 153, 434, 52, 43]
},
{
"id": "measure_profit",
"label": "Profit",
"values": [123, 45, 421, 465, 451, 56]
}
]
}
My expected output:
let expectdData = [
{
"Region": "East",
"County": "London",
"Sales": 100,
"Quantity": 85,
"Profit": 123
},
{
"Region": "East",
"County": "Italy",
"Sales": 156,
"Quantity": 34,
"Profit": 45
},
{
"Region": "West",
"County": "Germany",
"Sales": 432,
"Quantity": 153,
"Profit": 421
},
{
"Region": "SouthWest",
"County": "US",
"Sales": 462,
"Quantity": 434,
"Profit": 465
},
{
"Region": "South",
"County": "Russia",
"Sales": 25,
"Quantity": 52,
"Profit": 451
},
{
"Region": "NorthEast",
"County": "India",
"Sales": 100,
"Quantity": 43,
"Profit": 56
}
]
Here is my program to get this expected data:
let actualData = [];
inputData.dimensions.forEach((e,i) => {
let tempVal = e.label;
e.values.forEach((elem,index) => {
actualData[index] = new Object({
[tempVal] : elem
});
})
});
console.log(actualData);
But unfortunately, I only get the last item for every object. In my console it looks like this:
[
{ Profit: 123 },
{ Profit: 45 },
{ Profit: 421 },
{ Profit: 465 },
{ Profit: 451 },
{ Profit: 56 }
]
I think, in every iteration, it just overrides the "tempVal" variable. How to prevent this & how can I achieve the expected array of objects?

You are replacing the whole object on each iteration, you just need to create it if it does not exists, otherwise you can replace the key.
let actualData = [];
inputData.dimensions.forEach((e,i)=>{
let tempVal = e.label;
e.values.forEach((elem,index) => {
if (!actualData[index]) {
actualData[index] = {}
}
actualData[index][tempVal] = elem
})
});
console.log(actualData);

Using Array#reduce, iterate over dimension while updating a list of the resulting objects
In each iteration, use Array#forEach to iterate over the current values list and update the object at each index with label as key and the current value as value
const inputData = {
"dimensions": [
{
"id": "dimension_re",
"label": "Region",
"values": ["East", "East", "West", "SouthWest", "South","NorthEast"]
},
{
"id": "dimension_cnt",
"label": "County",
"values": ["London", "Italy", "Germany", "US", "Russia","India"]
},
{
"id": "measure_sales",
"label": "Sales",
"values": [100, 156, 432, 462, 25,100]
},
{
"id": "measure_qty",
"label": "Quantity",
"values": [85, 34, 153, 434, 52, 43]
},
{
"id": "measure_profit",
"label": "Profit",
"values": [123, 45, 421, 465, 451, 56]
}
]
};
const res = inputData.dimensions.reduce((acc, { label, values = [] }) => {
values.forEach((value, index) => {
acc[index] = { ...(acc[index] ?? {}), [label]: value };
});
return acc;
}, []);
console.log(res);

Since your index comes from the inner loop, you'll be replacing the values at actualData[index] each outer loop iteration, that's why you only end up with the last.
Try this reduce operation instead...
const inputData = {"dimensions":[{"id":"dimension_re","label":"Region","values":["East","East","West","SouthWest","South","NorthEast"]},{"id":"dimension_cnt","label":"County","values":["London","Italy","Germany","US","Russia","India"]},{"id":"measure_sales","label":"Sales","values":[100,156,432,462,25,100]},{"id":"measure_qty","label":"Quantity","values":[85,34,153,434,52,43]},{"id":"measure_profit","label":"Profit","values":[123,45,421,465,451,56]}]};
// Find the max number of `values`
const maxLength = Math.max(...inputData.dimensions.map(({ values }) => values.length));
const actualData = inputData.dimensions.reduce(
(arr, { label, values }) =>
arr.map((obj, i) => ({ ...obj, [label]: values[i] })),
Array.from(
{
length: maxLength,
},
() => ({}) // creates an array of empty objects
)
);
console.log(actualData);
.as-console-wrapper { max-height: 100% !important; }

Related

JavaScript count number of ocurrences in Array of Objects

I have an array of objects and I was trying to figure out how I can create a new array of objects that would display a new array of objects, but with an "occurences" field.
Here is my starting json array of objects:
const fakeJson = [
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-10",
"Popularity": 99,
"Country": "Canada"
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-11",
"Popularity": 99,
"Country": "Canada"
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "Canada"
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "China"
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "Canada"
}
Example result of what I would like. Notice the for Country Canada, one of them has Occurences: 2 for Date_Available "2022-04-12". How would I be able to accomplish this?
const resultJSON = [
{
"Date_Available": "2022-04-10",
"Popularity": 99,
"Country": "Canada",
"Occurrences" : 1
},
{
"Date_Available": "2022-04-11",
"Popularity": 99,
"Country": "Canada",
"Ocurrences" : 1
},
{
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "Canada",
"Occurrences" : 2
},
{
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "China",
"Occurrences" : 1
}
Here is what I have so far. My idea was to create a temporary obj with the country name, date available and occurrence set default to 1. Then based on the Date_Available, increase by 1 every time it appeared. However, if China and Canada both have the same date, then it seems to mess up the code and does not properly print the result.
let countNameMapping = {};
let finalArr = [];
for(let i = 0; i < fakeJson.length; i++){
let tempObj = {Country:fakeJson[i].Country, Date_Available: fakeJson[i].Date_Available, occurence: 1};
let countryName = fakeJson[i].Country;
let date = fakeJson[i].Date_Available;
if(countNameMapping[date] === undefined){
countNameMapping[countryName] = tempObj;
} else {
countNameMapping[date].occurence += 1;
}
}
for(let k in countNameMapping){
finalArr.push(countNameMapping[k])
}
console.log(finalArr)
const json = fakeJson.reduce((prev, curr) => {
const check = () => prev.findIndex(({ Date_Available, Country }) =>
curr.Date_Available === Date_Available &&
curr.Country === Country
);
check() === -1
? prev.push({
...Object.fromEntries(
Object.entries(curr).filter(([key]) => !key.match(/id|name|age/i))
),
Occurences: 1 })
: prev[check()].Occurences++
return prev
}, [])
console.log({ json });
Group by a custom key, eg Date_Available + Country
reduce() the result, create an array with the first object as base, then add Ocurrences, based on the amount of objects found (.length)
const data = [{"Id": 1, "Name": "John", "Age": 32, "Date_Available": "2022-04-10", "Popularity": 99, "Country": "Canada"}, {"Id": 1, "Name": "John", "Age": 32, "Date_Available": "2022-04-11", "Popularity": 99, "Country": "Canada"}, {"Id": 1, "Name": "John", "Age": 32, "Date_Available": "2022-04-12", "Popularity": 99, "Country": "Canada"}, {"Id": 1, "Name": "John", "Age": 32, "Date_Available": "2022-04-12", "Popularity": 99, "Country": "China"}, {"Id": 1, "Name": "John", "Age": 32, "Date_Available": "2022-04-12", "Popularity": 99, "Country": "Canada"}];
const grouped = data.reduce((p, c) => {
const key = c.Date_Available + c.Country;
(p[key] = p[key] || []).push(c);
return p;
}, {});
const result = Object.values(grouped).reduce((p, c) => [ ...p, { ...c[0], Ocurrences: c.length } ], []);
console.log(result)
Result:
[
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-10",
"Popularity": 99,
"Country": "Canada",
"Ocurrences": 1
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-11",
"Popularity": 99,
"Country": "Canada",
"Ocurrences": 1
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "Canada",
"Ocurrences": 2
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "China",
"Ocurrences": 1
}
]
you can use reduce and Object.values for that
like this
const groupBy = (data, ...keyGroup) => Object.values(data.reduce((res, item) => {
const key = keyGroup.map(k => item[k]).join('-')
const existing = res[key] || {...item, occurencies: 0}
return {
...res,
[key]: {...existing,occurencies: existing.occurencies + 1 }
}
}, {}))
const fakeJson = [
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-10",
"Popularity": 99,
"Country": "Canada"
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-11",
"Popularity": 99,
"Country": "Canada"
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "Canada"
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "China"
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "Canada"
}
]
console.log('by ID', groupBy(fakeJson, 'Id'))
console.log('by Country', groupBy(fakeJson, 'Country'))
console.log('by country and date', groupBy( fakeJson, 'Country', 'Date_Available'))

How do I remove properties from JavaScript object in array?

Let say I have this array as follows:
[
{
"id": 111,
"productName": "Chicken",
"variant": 9,
"variantName": "small",
"extrasSelected": [],
"price": 26,
"qty": "1"
},
{
"id": 112,
"productName": "Fish",
"variant": 25,
"variantName": "small",
"extrasSelected": [],
"price": 26,
"qty": "1"
}
]
How do I remove some of the properties so it will end up as follows?
[
{
"id": 111,
"variant": 9,
"extrasSelected": [],
"qty": "1"
},
{
"id": 112,
"variant": 25,
"extrasSelected": [],
"qty": "1"
}
]
The reasons why I need to do so, because I need to send the newObject data into my finalCart, but I need the productName in oldObject to display it on my view.
Just do a destructuring inside a .map
const data = [
{
"id": 111,
"productName": "Chicken",
"variant": 9,
"variantName": "small",
"extrasSelected": [],
"price": 26,
"qty": "1"
},
{
"id": 112,
"productName": "Fish",
"variant": 25,
"variantName": "small",
"extrasSelected": [],
"price": 26,
"qty": "1"
}
];
// 1
const result = data.map(({ id, variant, extrasSelected, qty }) => ({
id,
variant,
extrasSelected,
qty
}));
// Detailed explanation
// 2
// 2 is same as 1
const result2 = data.map((item => {
const { id, variant, extrasSelected, qty } = item;
return { id, variant, extrasSelected, qty };
}));
// 3
// 3 is same as 2
const result3 = data.map((item) => {
const id = item.id;
const variant = item.variant;
const extrasSelected = item.extrasSelected;
const qty = item.qty;
return {
id: id,
variant: variant,
extrasSelected: extrasSelected,
qty: qty
}
});
console.log(result);
/*
[
{ id: 111, variant: 9, extrasSelected: [], qty: '1' },
{ id: 112, variant: 25, extrasSelected: [], qty: '1' }
]
*/
You can use Array.prototype.map
[
{
"id": 111,
"productName": "Chicken",
"variant": 9,
"variantName": "small",
"extrasSelected": [],
"price": 26,
"qty": "1"
},
{
"id": 112,
"productName": "Fish",
"variant": 25,
"variantName": "small",
"extrasSelected": [],
"price": 26,
"qty": "1"
}
].map(({id, variant, extrasSelected, qty}) => ({id, variant, extrasSelected, qty}))
Variation on the above solutions. Use Array.Map and rest parameters.
const data = [{
"id": 111,
"productName": "Chicken",
"variant": 9,
"variantName": "small",
"extrasSelected": [],
"price": 26,
"qty": "1"
},
{
"id": 112,
"productName": "Fish",
"variant": 25,
"variantName": "small",
"extrasSelected": [],
"price": 26,
"qty": "1"
}
]
const result = data.map(({
productName,
variantName,
...rest
}) => rest);
console.log(JSON.stringify(result, null, 4));
There are many ways to do this.
If you actually want to delete the properties, here is one way:
let array = [
{
"id": 111,
"productName": "Chicken",
"variant": 9,
"variantName": "small",
"extrasSelected": [],
"price": 26,
"qty": "1"
},
{
"id": 112,
"productName": "Fish",
"variant": 25,
"variantName": "small",
"extrasSelected": [],
"price": 26,
"qty": "1"
}
]
array.forEach(obj => {
delete obj.variantName;
delete obj.price;
delete obj.productName;
});
console.log(array);

How can I group an array and get count of all the records having similar type/org

I have an array orglist with field organization. In the same array or new I need count of all the org present.
This is my array
{
"orgId": 56,
"org": "EDC",
"Id": 816,
},
{
"orgId": 37,
"org": "EDC",
"Id": 85425,
},
{
"orgId": 68,
"org": "AXC",
"Id": 85427,
},
{
"orgId": 28,
"org": "SEE",
"Id": 858,
}
I am looking for this output
{
"orgId": 56,
"org": "EDC",
"Id": 816,
"orgCount":"2"
},
{
"orgId": 37,
"org": "EDC",
"Id": 85425,
"orgCount":"2"
},
{
"orgId": 68,
"org": "AXC",
"Id": 85427,
"orgCount":"1"
},
....
I tried below solution but that provide me only count and org value and excluding all other fields
var counts = this.orglist.reduce((p, c) => {
var name = c.org;
if (!p.hasOwnProperty(name)) {
p[name] = 0;
}
p[name]++;
return p;
}, {});
How can I get expected output?
One way to do this is a two-stage process, first to count the occurrences of each org value, and then to add that property to the input objects:
let orglist = [{
"orgId": 56,
"org": "EDC",
"Id": 816,
},
{
"orgId": 37,
"org": "EDC",
"Id": 85425,
},
{
"orgId": 68,
"org": "AXC",
"Id": 85427,
},
{
"orgId": 28,
"org": "SEE",
"Id": 858,
}];
const counts = orglist.reduce((c, o) => {
c[o.org] = c[o.org] || 0;
c[o.org]++;
return c;
}, {});
orglist = orglist.map(({org, ...rest}) => ({ ...rest, org, "orgCount" : counts[org] }));
console.log(orglist);
You could try something like this:
const output = orgList.map((org1) => ({
...org1,
orgCount: orgList.filter(org2 => org2.org === org1.org).length
}));
You can use .map to add orgCount to each element using the counts object you have:
const orglist = [
{ "orgId": 56, "org": "EDC", "Id": 816 },
{ "orgId": 37, "org": "EDC", "Id": 85425 },
{ "orgId": 68, "org": "AXC", "Id": 85427 },
{ "orgId": 28, "org": "SEE", "Id": 858 }
];
const counts = orglist.reduce((p, c) => {
var name = c.org;
if (!p.hasOwnProperty(name)) p[name] = 0;
p[name]++;
return p;
}, {});
const res = orglist.map(e => ({...e, orgCount: counts[e.org]}));
console.log(res);
You can do something like this
const arr = [{
"orgId": 56,
"org": "EDC",
"Id": 816,
},
{
"orgId": 37,
"org": "EDC",
"Id": 85425,
},
{
"orgId": 68,
"org": "AXC",
"Id": 85427,
},
{
"orgId": 28,
"org": "SEE",
"Id": 858,
}
];
const response = Object.values(arr.reduce((res, el) => {
const count = res[el.org]?.orgCount || 0
const item = {...(res[el.org] || el), ...{orgCount: count + 1}}
res[el.org] = item
return res
}, {}))
console.log(response)

merge same properties of array of objects and create array of object within that array of object for different properties

This is my array
"status": "Success",
"results": 54,
"orders": [
{
"order_id": 261,
"image": "test1.png",
"productName": "test1",
"price": 2,
"quantity": 2,
"purAmt": 34,
"created_at": "2020-07-27T06:29:32.000Z",
"shopName": "abc"
},
{
"order_id": 261,
"image": "test2.png",
"productName": "test2",
"price": 30,
"quantity": 1,
"purAmt": 34,
"created_at": "2020-07-27T06:29:32.000Z",
"shopName": "abc"
},
]
I want to combine properties with same name and create array of object within a object.
expected output
"status": "Success",
"results": 54,
"orders": [
{
"order_id": 261,
"purAmt": 34,
"created_at": "2020-07-27T06:29:32.000Z",
"shopName": "abc"
products : [
{
"productName": "test1",
"price": 2,
"quantity": 2,
"image": "test1.png",
},
{
"productName": "test2",
"price": 5,
"quantity": 3,
"image": "test2.png",
},
}
]
I would be better if I get the solution using reduce function and without any libraries like lodash
My attempt of doing it using reduce fcn
var result = Object.values(
data.reduce(
(acc, { productName, price, image, quantity, ...rest }) => {
acc[rest.orderID] = acc[rest.orderID] || { ...rest, products: [] };
acc[rest.orderID].products.push({
productName,
price,
image,
quantity,
});
return acc;
},
{},
),
);
This should work for you
orders = [
{
order_id: 261,
image: "test1.png",
productName: "test1",
price: 2,
quantity: 2,
purAmt: 34,
created_at: "2020-07-27T06:29:32.000Z",
shopName: "abc",
},
{
order_id: 261,
image: "test2.png",
productName: "test2",
price: 30,
quantity: 1,
purAmt: 34,
created_at: "2020-07-27T06:29:32.000Z",
shopName: "abc",
},
];
const res = Object.values(
orders.reduce((acc, { image, productName, price, quantity, ...rest }) => {
if (!acc[rest.order_id]) {
acc[rest.order_id] = { products: [] };
}
acc[rest.order_id] = {
...acc[rest.order_id],
...rest,
products: [
...acc[rest.order_id].products,
{
image,
productName,
price,
quantity,
},
],
};
return acc;
}, {})
);
console.log(res);
Extended Version: I extend it, so there are now different order_id's considered. For example I add a id 262 which creates another element in orders-array.
let data = { "status": "Success",
"results": 54,
"orders": [
{
"order_id": 261,
"image": "test1.png",
"productName": "test1",
"price": 2,
"quantity": 2,
"purAmt": 34,
"created_at": "2020-07-27T06:29:32.000Z",
"shopName": "abc"
},
{
"order_id": 262,
"image": "test3.png",
"productName": "test3",
"price": 70,
"quantity": 5,
"purAmt": 17,
"created_at": "2020-07-19T06:29:32.000Z",
"shopName": "xyz"
},
{
"order_id": 261,
"image": "test2.png",
"productName": "test2",
"price": 30,
"quantity": 1,
"purAmt": 34,
"created_at": "2020-07-27T06:29:32.000Z",
"shopName": "abc"
},
]};
let orderIndex =[];
let orders = [];
data.orders.forEach(orderObj => {
let order;
let index = orderIndex.indexOf(orderObj.order_id);
if (index == -1) {
orderIndex.push(orderObj.order_id);
order = {};
orders.push(order);
['order_id', 'purAmt', 'created_at', 'shopName'].forEach( elem => {
order[elem] = orderObj[elem];
order.products = [];
});
} else {
order = orders[index];
}
let product = {};
['productName', 'price', 'image', 'quantity'].forEach( elem => {
product[elem] = orderObj[elem];
});
order.products.push(product);
});
let result = {
status: data.status,
results: data.results,
orders: orders
}
console.log(result);

ES6: Find an object in an array by one of its properties

I'm trying to figure out how to do this in ES6...
I have this array of objects..
const originalData=[
{"investor": "Sue", "value": 5, "investment": "stocks"},
{"investor": "Rob", "value": 15, "investment": "options"},
{"investor": "Sue", "value": 25, "investment": "savings"},
{"investor": "Rob", "value": 15, "investment": "savings"},
{"investor": "Sue", "value": 2, "investment": "stocks"},
{"investor": "Liz", "value": 85, "investment": "options"},
{"investor": "Liz", "value": 16, "investment": "options"}
];
..and this new array of objects where I want to add each person's total value of their investment types (stocks, options, savings)..
const newData = [
{"investor":"Sue", "stocks": 0, "options": 0, "savings": 0},
{"investor":"Rob", "stocks": 0, "options": 0, "savings": 0},
{"investor":"Liz", "stocks": 0, "options": 0, "savings": 0}
];
I loop through originalData and save each property of the "current object" in a let..
for (let obj of originalData) {
let currinvestor = obj.investor;
let currinvestment = obj.investment;
let currvalue = obj.value;
..but here I want to find the obect in newData that has the property = currinvestor (for the "investor" key)
...then add that investment type's (currinvestment) value (currvalue)
}
newData.find(x => x.investor === investor)
And the whole code:
const originalData = [
{ "investor": "Sue", "value": 5, "investment": "stocks" },
{ "investor": "Rob", "value": 15, "investment": "options" },
{ "investor": "Sue", "value": 25, "investment": "savings" },
{ "investor": "Rob", "value": 15, "investment": "savings" },
{ "investor": "Sue", "value": 2, "investment": "stocks" },
{ "investor": "Liz", "value": 85, "investment": "options" },
{ "investor": "Liz", "value": 16, "investment": "options" },
];
const newData = [
{ "investor": "Sue", "stocks": 0, "options": 0, "savings": 0 },
{ "investor": "Rob", "stocks": 0, "options": 0, "savings": 0 },
{ "investor": "Liz", "stocks": 0, "options": 0, "savings": 0 },
];
for (let {investor, value, investment} of originalData) {
newData.find(x => x.investor === investor)[investment] += value;
}
console.log(newData);
.as-console-wrapper.as-console-wrapper { max-height: 100vh }
I would use some derivative of this:
var arrayFindObjectByProp = (arr, prop, val) => {
return arr.find( obj => obj[prop] == val );
};

Categories