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);
Related
I am attempting to update an existing array of objects by adding a new object:
const oldArray = [{ name: 'First', value: 'one' }, { name: 'Second', value: 'two' }, { name: 'Third', value: 'three' }]
const newArray = [...oldArray, { name: 'Fourth', value: 'four' }]
My intention, however, is to set up newArray so that the Fourth object becomes the 3rd item (index 2) in oldArray. How can I go about setting up newArray so that the new object is injected as the 3rd item in the ...oldArray spread operator, without having to write out all of the oldArray items again in newArray?
You can use .slice() along with the spread syntax.
const oldArray = [{ name: 'First', value: 'one' }, { name: 'Second', value: 'two' }, { name: 'Third', value: 'three' }]
const newArray = [...oldArray.slice(0, 2), { name: 'Fourth', value: 'four' }, ...oldArray.slice(2)];
console.log(newArray);
You would need to do two spreads using slice
const oldArray = [{ name: 'First', value: 'one' }, { name: 'Second', value: 'two' }, { name: 'Third', value: 'three' }]
const newArray = [...oldArray.slice(0,2), { name: 'Fourth', value: 'four' }, ...oldArray.slice(2)]
console.log(newArray.map(x => x.name));
other option is to just use splice()
const oldArray = [{ name: 'First', value: 'one' }, { name: 'Second', value: 'two' }, { name: 'Third', value: 'three' }]
const newArray = [...oldArray]
newArray.splice(2,0,{ name: 'Fourth', value: 'four' });
console.log(newArray.map(x => x.name));
I'm going to be given an array of label text strings to match to values in an array. The array of objects is static but the array of text strings will be dynamic from user input. I want to know the best es6 way of setting this up using filter or map.
Here is the static array of objects:
const counts = [
{label: '0-0', value: 1},
{label: '0-1', value: 2},
{label: '0-2', value: 3},
{label: '1-0', value: 4},
{label: '1-1', value: 5},
{label: '1-2', value: 6},
{label: '2-0', value: 7},
{label: '2-1', value: 8},
{label: '2-2', value: 9},
{label: '3-0', value: 10},
{label: '3-1', value: 11},
{label: '3-2', value: 12},
];
This is an example of the array of keys I'll get:
Array [
"0-2",
"1-2",
"2-0",
"3-1"
]
So the results I want to get are an array with the values:
[3,6,7,11]
I have ways of doing this sloppily checking each value one by one, I'm just not sure what to use like filter, map, reduce, or find.
We can use filter and map function of JS for this.
let test = [
"0-2",
"1-2",
"2-0",
"3-1"
];
let counts = [{
label: '0-0',
value: 1
},
{
label: '0-1',
value: 2
},
{
label: '0-2',
value: 3
},
{
label: '1-0',
value: 4
},
{
label: '1-1',
value: 5
},
{
label: '1-2',
value: 6
},
{
label: '2-0',
value: 7
},
{
label: '2-1',
value: 8
},
{
label: '2-2',
value: 9
},
{
label: '3-0',
value: 10
},
{
label: '3-1',
value: 11
},
{
label: '3-2',
value: 12
},
];
let answer = counts.filter(item => (
test.includes(item.label)
)).map(item => item.value)
console.log(answer);
You can use array#reduce and add the matched label's value in that using array#find.
const counts = [{ label: '0-0', value: 1 }, { label: '0-1', value: 2 }, { label: '0-2', value: 3 }, { label: '1-0', value: 4 }, { label: '1-1', value: 5 }, { label: '1-2', value: 6 }, { label: '2-0', value: 7 }, { label: '2-1', value: 8 }, { label: '2-2', value: 9 }, { label: '3-0', value: 10 }, { label: '3-1', value: 11 }, { label: '3-2', value: 12 }, ],
input = [ "0-2", "1-2", "2-0", "3-1" ],
output = input.reduce((arr, label) => {
const matched = counts.find(o => o.label === label);
if(matched) arr.push(matched.value);
return arr;
},[]);
console.log(output);
You can create a Map which will act as a look-up-table (lut) for labels and their associated values. Using the Map you can then .map() your array of labels to be the value from the Map object.
By using this approach, you will only need to loop through your counts array once, and your labels array (arr) once, which will allow you to avoid "checking each value one by one", providing you with a complexity of ~ O(n + k), rather than O(nk):
const counts = [{label:"0-0",value:1},{label:"0-1",value:2},{label:"0-2",value:3},{label:"1-0",value:4},{label:"1-1",value:5},{label:"1-2",value:6},{label:"2-0",value:7},{label:"2-1",value:8},{label:"2-2",value:9},{label:"3-0",value:10},{label:"3-1",value:11},{label:"3-2",value:12}];
const arr = ["0-2", "1-2", "2-0", "3-1"];
const lut = new Map(counts.map(({label, value}) => [label, value]));
const res = arr.map(label => lut.get(label));
console.log(res);
I am trying to filter an array of objects and assign multiple variables based on if there is a match or not.
The reason for this, is that I can then use the variable in a string literal, displaying the value.
I have managed to break it down, but I see that I am repeating myself a lot and believe this is not the most efficient way.
Any help would be greatly appreciated.
let stats = [{name: "goals", value: 5},
{name: "losses", value: 20},
{name: "wins", value: 48},
{name: "draws", value: 23},
{name: "fwd_pass", value: 1533},
{name: "goal_assist", value: 2},
{name: "appearances", value: 80},
{name: "mins_played", value: 6953},
{name: "backward_pass", value: 308}]
//const { player , stats } = playerData[0]
const appearances = stats.filter(({name} , i) => {
return name == "appearances"
});
const goals = stats.filter(({name} , i) => {
return name == "goals"
});
const assists = stats.filter(({name} , i) => {
return name == "goal_assist"
});
const mins = stats.filter(({name} , i) => {
return name == "mins_played"
});
const fwdPass = stats.filter(({name} , i) => {
return name == "fwd_pass"
});
const backPass = stats.filter(({name} , i) => {
return name == "backward_pass"
});
Your approach returns arrays for each variable. An alternative is creating an object which keys are the names. That way, you will be able to access using the name and get the specific object.
let stats = [{name: "goals", value: 5},{name: "losses", value: 20},{name: "wins", value: 48},{name: "draws", value: 23},{name: "fwd_pass", value: 1533},{name: "goal_assist", value: 2},{name: "appearances", value: 80},{name: "mins_played", value: 6953},{name: "backward_pass", value: 308}],
variables = stats.reduce((a, c) => Object.assign(a, {[c.name]: c}), Object.create(null));
console.log(`Access through key: ${variables.fwd_pass.value}`);
You can create a single function to which you pass the name to filter the data:
let stats = [{ name: "goals", value: 5 }, { name: "losses", value: 20 }, { name: "wins", value: 48 }, { name: "draws", value: 23 }, { name: "fwd_pass", value: 1533 }, { name: "goal_assist", value: 2 }, { name: "appearances", value: 80 }, { name: "mins_played", value: 6953 }, { name: "backward_pass", value: 308 } ]
const fnFilter = (name) => stats.find(x => x.name == name)
console.log(fnFilter('appearances'))
console.log(fnFilter('backward_pass'))
Or you can create an object map and access by key:
let stats = [{ name: "goals", value: 5 }, { name: "losses", value: 20 }, { name: "wins", value: 48 }, { name: "draws", value: 23 }, { name: "fwd_pass", value: 1533 }, { name: "goal_assist", value: 2 }, { name: "appearances", value: 80 }, { name: "mins_played", value: 6953 }, { name: "backward_pass", value: 308 } ]
const index = stats.reduce((r,c) => (r[c.name] = c, r), {})
console.log(index['appearances'])
console.log(index['backward_pass'])
The code will be a lot shorter if you use an object and assign the names as properties. It will always be longer if you want to camel case your variables or properties. Unless you use regular expressions or string manipulations to dynamically convert your name values into camelCase. But that's unnecessary stretch
let stats = [{name: "goals", value: 5},
{name: "losses", value: 20},
{name: "wins", value: 48},
{name: "draws", value: 23},
{name: "fwd_pass", value: 1533},
{name: "goal_assist", value: 2},
{name: "appearances", value: 80},
{name: "mins_played", value: 6953},
{name: "backward_pass", value: 308}]
//const { player , stats } = playerData[0]
const statsObj = {};
stats.forEach((item) => { statsObj[item.name] = item; } );
console.log(statsObj.wins); //outputs {name: "wins", value: 48}
console.log(statsObj.wins.value); //48
I am creating a sunburst chart in highcharts and I am having trouble creating layers in the array.
For instance, the headers array is layer 2 and data array is layer 3.
I need to compare the headername with groups from data and create a new array giving both a child id and a parent id.
Have posted my current solution below the code.
const headers = ['Cars', 'Fruits', 'Food'];
const data = [{
group: 'Cars',
name: 'BMW',
value: '25641'
}, {
group: 'Fruits',
name: 'Apple',
value: '45876'
},
{
group: 'Cars',
name: 'Benz',
value: '65784'
},
{
group: 'Cars',
name: 'Toyota',
value: '254'
},
{
group: 'Food',
name: 'Pizza',
value: '87535'
},
{
group: 'Cars',
name: 'Honda',
value: '65796'
},
{
group: 'Fruits',
name: 'Banana',
value: '98631'
},
{
group: 'Fruits',
name: 'Orange',
value: '87563'
},
{
group: 'Food',
name: 'Burger',
value: '78324'
},
{
group: 'Fruits',
name: 'Mango',
value: '24598'
}
]
This is what I tried.
const newArray = headers.map(function(itemA, indexA) {
return data.map(function(itemB, indexB) {
return {
id: `3.${indexB + 1}`,
parentId: `2.${indexA + 1}`,
value: itemB.value,
name: itemB.name
}
})
})
This is the output I expect:
const newArray = [{
id: '3.1',
parentId: '2.1',
name: 'BMW',
value: '25641'
}, {
id: '3.2',
parentId: '2.2',
name: 'Apple',
value: '45876'
},
{
id: '3.3',
parentId: '2.1',
name: 'Benz',
value: '65784'
},
{
id: '3.4',
parentId: '2.1'
name: 'Toyota',
value: '254'
},
{
id: '3.5',
parentId: '2.3',
name: 'Pizza',
value: '87535'
},
{
id: '3.6',
parentId: '2.1',
name: 'Honda',
value: '65796'
},
{
id: '3.7',
parentId: '2.2',
name: 'Banana',
value: '98631'
},
{
id: '3.8',
parentId: '2.2',
name: 'Orange',
value: '87563'
},
{
id: '3.9',
parentId: '2.3',
name: 'Burger',
value: '78324'
},
{
id: '3.10',
parentId: '2.2',
name: 'Mango',
value: '24598'
}
]
You don't need the nested maps — it will cause nested arrays of results. You just need one because there is a 1-to1 relationship between data and your expected output. You can just map() over data and lookup the parent index as you go.
const headers = ['Cars', 'Fruits', 'Food'];
const data = [{group: 'Cars',name: 'BMW',value: '25641'}, {group: 'Fruits',name: 'Apple',value: '45876'},{group: 'Cars',name: 'Benz',value: '65784'},{group: 'Cars',name: 'Toyota',value: '254'},{group: 'Food',name: 'Pizza',value: '87535'},{group: 'Cars',name: 'Honda',value: '65796'},{group: 'Fruits',name: 'Banana',value: '98631'},{group: 'Fruits',name: 'Orange',value: '87563'},{group: 'Food',name: 'Burger',value: '78324'},{group: 'Fruits',name: 'Mango',value: '24598'}]
const newArray = data.map(function(itemB, indexB) {
let parentIndex = headers.indexOf(itemB.group) // just find the parent index
return {
id: `3.${indexB + 1}`,
parentId: `2.${parentIndex + 1}`,
value: itemB.value,
name: itemB.name
}
})
console.log(newArray)
I have the following collection of data
[{
id: '1',
date: '2017-01-01',
value: 2
},
{
id: '2',
date: '2017-01-02',
value: 3
},
{
id: '3',
value: 3
},
id: '4',
date: '2017-01-02',
value: 3
}]
I want to delete any object that does not have the 'date' property. In the example above, the object with the id 3 should be deleted.
The finished object should look like this
[{
id: '1',
date: '2017-01-01',
value: 2
},
{
id: '2',
date: '2017-01-02',
value: 3
},
id: '4',
date: '2017-01-02',
value: 3
}]
I tried to find and delete a undefined value with lodash. It does not work. The object looks exactly as it is entering.
_.each(obj, (val) => {
_.remove(val, value => value['XXX-BUDAT'] === undefined);
});
How can I use lodash for this purpose?
Thanks in advance
You can use .filter(), Object.keys(), and .includes()
let input = [
{ id: '1', date: '2017-01-01', value: 2},
{ id: '2', date: '2017-01-02', value: 3},
{ id: '3', value: 3 },
{ id: '4', date: '2017-01-02', value: 3 }
]
let output = input.filter(obj => Object.keys(obj).includes("date"));
console.log(output);
You can filter the array based on that property like this:
const initial = [{
id: '1',
date: '2017-01-01',
value: 2
},
{
id: '2',
date: '2017-01-02',
value: 3
},
{
id: '3',
value: 3
}, { // this left curly brace was missing!, check that out
id: '4',
date: '2017-01-02',
value: 3
}
];
const finalR = initial.filter((obj) => obj.hasOwnProperty('date') && !!obj.date);
console.log(finalR);
You can use Array#filter and Object#hasOwnProperty to do so:
var newArray = oldArray.filter(function(obj) {
return obj.hasOwnProperty("date");
});
Which can be shortened out using an arrow function:
var newArray = oldArray.filter(obj => obj.hasOwnProperty("date"));
Lodash solution:
var newArray = _.filter(oldArray, obj => _.has(obj, "date"));
Example:
var oldArray = [{id: '1', date: '2017-01-01', value: 2 }, { id: '2', date: '2017-01-02', value: 3 }, { id: '3', value: 3 }, {id: '4', date: '2017-01-02', value: 3}];
var newArray = oldArray.filter(obj => obj.hasOwnProperty("date"));
console.log(newArray);
You can use Array.prototype.filter. In addition, you can use ES6 object assignment destructiring to make it concise:
var data=[{id:'1',date:'2017-01-01',value:2},{id:'2',date:'2017-01-02',value:3},{id:'3',value:3},{id:'4',date:'2017-01-02',value:3}];
var result = data.filter(({date}) => date);
console.log(result)
First of all your array of object is not valid, fix it by wrapping the last object element with preceding curly brace {. See Array.prototype.filter() and Object.prototype.hasOwnProperty() that'll check your current object item has the date key or not? if it has then it'll return that object other wise that item will not return.
var array_of_object = [{
id: '1',
date: '2017-01-01',
value: 2
},
{
id: '2',
date: '2017-01-02',
value: 3
},
{
id: '3',
value: 3
},
{ //missing brace here
id: '4',
date: '2017-01-02',
value: 3
}
];
function filterByValue(item) {
return item.hasOwnProperty('date');
}
var arrByID = array_of_object.filter(filterByValue);
console.log(arrByID);
This is a native javascript solution:
var arr = [
{id: '1', date: '2017-01-01', value: 2},
{id: '2', date: '2017-01-02', value: 3},
{id: '3', value: 3},
{id: '4', date: '2017-01-02', value: 3}
]
for(var i = 0; i < arr.length; i++) {
if(!arr[i].hasOwnProperty("date")) {
arr.splice(i,1);
}
}
console.log(arr);