This question already has answers here:
Use a concatenated (dynamic) string as JavaScript object key? [duplicate]
(6 answers)
Is it possible to add dynamically named properties to JavaScript object?
(20 answers)
how to concatenate (variable + object key names) to get the object values in dot notation [duplicate]
(1 answer)
Closed 2 years ago.
I have an array of objects like this:
const data = [
{name: 'Page A', count: 4000},
{name: 'Page B', count: 3000},
{name: 'Page C', count: 2000},
];
I need to add an index number to the count property so the list would look like this:
const wantedArray = [
{name: 'Page A', count1: 4000},
{name: 'Page B', count2: 3000},
{name: 'Page C', count3: 2000},
];
I tried this but got this ts error: Operator '+' cannot be applied to types '{ name: any; count: any; }' and 'number'.ts(2365)
let wantedArray: any = []
data.map((object: any, index) => {
wantedArray.push({
name: object.name,
count+index: start.count,
});
});
What is the best solution to achieve this? Thank you.
Simply assign wantedArray to map of the data array, also use [] to assign values with dynamic key.
const data = [
{name: 'Page A', count: 4000},
{name: 'Page B', count: 3000},
{name: 'Page C', count: 2000},
];
let wantedArray = data.map((obj, index) => {
return {
name: obj.name,
[`count${index+1}`]: obj.count
}
});
console.log(wantedArray)
Use bracket notation - [key] for the dynamic key.
const data = [{
name: 'Page A',
count: 4000
},
{
name: 'Page B',
count: 3000
},
{
name: 'Page C',
count: 2000
},
];
const wantedArray = data.map((obj, index) => ({
name: obj.name,
[`count${index+1}`]: obj.count,
}));
console.log(wantedArray);
Use [variablename] to write inside a variable name.
And since the index starts at 0, we do + 1.
const data = [
{name: 'Page A', count: 4000},
{name: 'Page B', count: 3000},
{name: 'Page C', count: 2000},
];
const result = data.map((n, i) => {
return {
name: n.name,
[`count${i+1}`]: n.count,
}
});
console.log(result);
Or if you want to push it into a new array.
const data = [
{name: 'Page A', count: 4000},
{name: 'Page B', count: 3000},
{name: 'Page C', count: 2000},
];
let wantedArray = [];
data.forEach((object, index) => {
return wantedArray.push({
name: object.name,
[`count${index+1}`]: object.count,
});
});
console.log(wantedArray);
Related
This question already has answers here:
How to group by and sum an array of objects? [duplicate]
(2 answers)
Sum JavaScript object propertyA values with the same object propertyB in an array of objects
(12 answers)
Closed last month.
I have an array of objects that I want to reduce.
I have this array of products in my state objArr:
]
0: {item: 'Item 1', value: 1}
1: {item: 'Item 2' value: 3}
2: {item: 'Item 3', value: 5}
3: {item: 'Item 1', value: 3}
4: {item: 'Item 2', value: 5}
]
But I want it to be:
[
0: {item: 'Item 1', value: 4}
1: {item: 'Item 2' value: 8}
2: {item: 'Item 3', value: 5}
]
I only manage to delete an entire object and not just a key value pair. Can someone help me?
This is the closest I can get:
const findDuplicates = () => {
return objArr?.reduce((arr, item) => {
const removed = arr?.filter(i => i.item !== item.item)
const dup = [...removed, item]
return dup
}, [])
}
Output:
[
0: {item: 'Item 3', value: 5}
1: {item: 'Item 1', value: 3}
2: {item: 'Item 2', value: 5}
]
As you mention, use reduce and value property to sum them up :
const groupByItem = objArr.reduce((acc, curr) => {
if (acc[curr.item]) {
acc[curr.item].value += curr.value;
} else {
acc[curr.item] = { item: curr.item, value: curr.value };
}
return acc;
}, {});
const groupedArray = Object.values(groupByItem);
I need to split data from BE and then sort by some prefix.
Example of array ->
let dataFromBE = [
{name: 'item one' , id: 1},
{name: 'item two' , id: 2},
{name: 'TEST:1' , id: 3},
{name: 'TEST:1' , id: 4},
{name: 'ASC item' , id: 5},
{name: 'some item' , id: 6},
{name: 'ASC item' , id: 6},
];
What I need ? To sort items with prefix 'TEST:' in first ( top ) array and sort other items alphabetically.
This is my way but maybe is not enough good
const itemsWithPrefix = tags?.filter(
(item) => item.name && item.name.toUpperCase().startsWith('TEST:')
);
const otherItems = tags?.filter(
(item) => item.name && !item.name.toUpperCase().startsWith('TEST:')
);
let mergedArr: any[] = [];
if (itemsWithPrefix && otherItems) {
mergedArr = [...itemsWithPrefix, ...otherItems?.sort((a, b) => (a.name > b.name ? 1 : -1))];
}
Is there a possibility for this to be done without creating two separate sequences, but only iteration through one? Thank you. And any other attempt to be more readable than mine is totally fine.
Use sort() with a custom sort function that gives priority to "TEST"
let dataFromBE = [
{name: 'item one' , id: 1},
{name: 'item two' , id: 2},
{name: 'TEST:1' , id: 3},
{name: 'TEST:1' , id: 4},
{name: 'ASC item' , id: 5},
{name: 'some item' , id: 6},
{name: 'ASC item' , id: 6},
];
dataFromBE.sort((a,b) => {
const aIsTEST = a.name.toUpperCase().startsWith('TEST:');
const bIsTEST = b.name.toUpperCase().startsWith('TEST:');
if (aIsTEST && !bIsTEST) return -1;
if (!aIsTEST && bIsTEST) return 1;
return a.name.localeCompare(b.name);
});
console.log(dataFromBE);
you can use includes() method instead of comparison inorder to avoid exact matching
let dataFromBE = [
{name: 'item one' , id: 1},
{name: 'TEST: ' , id: 2},
{name: 'TEST:1' , id: 3},
{name: 'TEST:2' , id: 4},
{name: 'ASC item' , id: 5},
{name: 'some item' , id: 6},
{name: 'ASC item' , id: 6},
];
dataFromBE.sort((a,b) => {
if (a.name.includes("TEST:") && !(b.name.includes("TEST:"))) return -1;
if (!(a.name.includes("TEST:")) && b.name.includes("TEST:")) return 1;
return a.name.localeCompare(b.name);
});
console.log(dataFromBE)
try using sort
let dataFromBE = [
{name: 'item one' , id: 1},
{name: 'item two' , id: 2},
{name: 'TEST:1' , id: 3},
{name: 'TEST:1' , id: 4},
{name: 'ASC item' , id: 5},
{name: 'some item' , id: 6},
{name: 'ASC item' , id: 6},
];
dataFromBE.sort((a, b) => {
const nameA = a.name.toUpperCase();
const nameB = b.name.toUpperCase();
if (nameA.startsWith("TEST") && !nameB.startsWith("TEST")) return -1;
if (!nameA.startsWith("TEST") && nameB.startsWith("TEST")) return 1;
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
return 0;
});
console.log(dataFromBE)
I have an array of object which has an inner array of object, I want to push the id of parent object to each child object.
a = [
{id: 'abc', stage: [{name: 'car' , value: '123'},{name: 'bus' , value: '345'},{name: 'truck' , value: '567'}],
{id: 'def', stage: [{name: 'bike' , value: '890'},{name: 'cycle' , value: '123'},{name: 'car' , value: '456'}]}
]
expected output = [
{name: 'car' , value: '123', id: 'abc'},{name: 'bus' , value: '345', 'abc'},{name: 'truck' , value: '567', 'abc'}, {name: 'bike' , value: '890', id: 'def'},{name: 'cycle' , value: '123',id: 'def',id: 'def'},{name: 'car' , value: '456', id: 'def'}
]
Im able to get the only the stage but not able to push id to each object. pls help
const getAllStages = [].concat(...map(a, el => el.stage));
console.log(getAllStages )
Use .map() again to add el.id to each element of el.stage.
You can use .flatMap() in the outer mapping to concatenate all the results into a single array.
const a = [
{id: 'abc', stage: [{name: 'car' , value: '123'},{name: 'bus' , value: '345'},{name: 'truck' , value: '567'}]},
{id: 'def', stage: [{name: 'bike' , value: '890'},{name: 'cycle' , value: '123'},{name: 'car' , value: '456'}]}
]
result = a.flatMap(({
id,
stage
}) => stage.map(s => ({
id: id,
...s
})));
console.log(result);
If you're trying to merge in id:
let remapped = a.map(e => ({ id: a.id, ...e }));
Where that converts each entry into an object inheriting the a.id value and adding on whatever else is in the object.
Here is a example and result :)
a.forEach(function(row) {
row.stage.map(function (child) {child.id = row.id})
})
result:
[{"id":"abc","stage":[{"name":"car","value":"123","id":"abc"},{"name":"bus","value":"345","id":"abc"},{"name":"truck","value":"567","id":"abc"}]},{"id":"def","stage":[{"name":"bike","value":"890","id":"def"},{"name":"cycle","value":"123","id":"def"},{"name":"car","value":"456","id":"def"}]}]
You can write like this without using libraries
let a = [
{
id: 'abc', stage:
[
{ name: 'car', value: '123' },
{ name: 'bus', value: '345' },
{ name: 'truck', value: '567' }
]
},
{
id: 'def', stage:
[
{ name: 'bike', value: '890' },
{ name: 'cycle', value: '123' },
{ name: 'car', value: '456' }
]
}
]
let output = [];
for (const element of a) {
for (const stageElement of element.stage) {
let newElement = {
name: stageElement.name,
value: stageElement.value,
id: element.id
};
output.push(newElement);
}
}
const a = [
{id: 'abc', stage: [{name: 'car' , value: '123'},{name: 'bus' , value: '345'},{name: 'truck' , value: '567'}]},
{id: 'def', stage: [{name: 'bike' , value: '890'},{name: 'cycle' , value: '123'},{name: 'car' , value: '456'}]}
]
a.forEach(item => {
const itemId = item.id;
const stages = item.stage;
stages.forEach(stage => {
stage['id'] = itemId;
})
});
console.log(a);
This question already has answers here:
Add prefix to each array object with javascript
(3 answers)
Closed 4 years ago.
I have an array like below:
var arrItems = [
{id: '1', value: 'table', price: 100},
{id: '2', value: 'chair', price: 200},
{id: '3', value: 'bed', price: 300},
];
How to prefix a string 'AB' in each item's id in the array?
My result array should be :
var arrItems = [
{id: 'AB1', value: 'table', price: 100},
{id: 'AB2', value: 'chair', price: 200},
{id: 'AB3', value: 'bed', price: 300},
];
Can I achieve it using the Javascript in map function?
The map() method creates a new array with the results of calling a provided function on every element in the calling array.
I also used the Spread syntax to copy object of collection and for easy property change.
var arrItems = [
{id: '1', value: 'table', price: 100},
{id: '2', value: 'chair', price: 200},
{id: '3', value: 'bed', price: 300},
];
var result = arrItems.map(i => ({...i, id: 'AB' + i.id }))
console.log(result)
You can loop through the array and change the of each object in that array:
var arrItems = [
{id: '1', value: 'table', price: 100},
{id: '2', value: 'chair', price: 200},
{id: '3', value: 'bed', price: 300},
];
// loop through the array and concatenate 'AB' to the id of each object in that array
arrItems.forEach(function(el) {
el.id = 'AB' + el.id;
});
// just for the demo purpose, we'll log the array in the console
var output = 'Result:\n';
arrItems.forEach(function(el) {
output += 'id: ' + el.id + ', value: ' + el.value + ', price: ' + el.price +'\n';
});
console.log(output);
Hope I pushed you further.
I have an array of objects:
var obj = [
{name: 'a1', type: 't1', price: 10},
{name: 'a1', type: 't1', price: 10},
{name: 'a2', type: 't2', price: 10},
{name: 'a1', type: 't2', price: 10},
];
I need to get this result:
[
{name: 'a1', type: 't1', price: 20},
{name: 'a1', type: 't2', price: 10},
{name: 'a2', type: 't2', price: 10}
]
I want to sum the item if, and only if, the properties name and type match. Any idea?
You can use reduce to group it into an object. Use Object.values to convert the object into array.
var obj = [
{name: 'a1', type: 't1', price: 10},
{name: 'a1', type: 't1', price: 10},
{name: 'a2', type: 't2', price: 10},
{name: 'a1', type: 't2', price: 10},
];
var result = Object.values(obj.reduce((c, v) => {
let k = v.name + '-' + v.type;
c[k] = c[k] || {...v, price: 0};
c[k].price += v.price;
return c;
}, {}));
console.log(result);
You could reduce into a Map and turn it back into an array:
var obj = [
{name: 'a1', type: 't1', price: 10},
{name: 'a1', type: 't1', price: 10},
{name: 'a2', type: 't2', price: 10},
{name: 'a1', type: 't2', price: 10},
];
const map = obj.reduce((map, { name, type, price }) => {
console.log('iter');
const key = name + '_' + type;
return map.set(key, (map.get(key) || 0) + price);
}, new Map());
const output = [...map.entries()].map(([key, val]) => {
const [name, type] = key.split('_');
return { name, type, price: val };
});
console.log(output);
You can try following (sum and sort by name and type)
var obj = [
{name: 'a1', type: 't1', price: 10},
{name: 'a1', type: 't1', price: 10},
{name: 'a2', type: 't2', price: 10},
{name: 'a1', type: 't2', price: 10},
];
// First create the result object where sum of price is done
var result = obj.reduce((a,c) => {
if(a[c.name + "_" + c.type]) {
a[c.name + "_" + c.type].price += c.price;
} else {
a[c.name + "_" + c.type] = c;
}
return a;
}, {});
// Get the values in an array
result = Object.values(result);
// Sort the array by name and then type
result.sort((a,b) => {
if(a.name === b.name) return a.type.localeCompare(b.type);
return a.name.localeCompare(b.name);
});
console.log(result);
You can use of Array.reduce to build up a new array considering your requirements.
const obj = [{
name: 'a1',
type: 't1',
price: 10,
},
{
name: 'a1',
type: 't1',
price: 10,
},
{
name: 'a2',
type: 't2',
price: 10,
},
{
name: 'a1',
type: 't2',
price: 10,
},
].reduce((tmp, x) => {
// Look if there is already a matching item in tmp
const findItem = tmp.find(y => y.name === x.name && y.type === x.type);
// It's not inside
if (!findItem) {
tmp.push(x);
return tmp;
}
// it is inside
findItem.price += x.price;
return tmp;
}, []);
console.log(obj);