Add property to each object of specific structure JS? [closed] - javascript

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I have an object :
const obj = {
app: {
groups: [{ name: 'name', values: 'values' }, { name: 'name1', values: 'values1' }]
},
app2: {
groups: [{ name: 'name2', values: 'values' }, { name: 'name2', values: 'values4' }]
},
app3: {
groups: [{ name: 'name5', values: 'values5' }, { name: 'name4', values: 'values4' }]
}
};
How can I add to each object in groups id with the same value as in name prop to get this:
const obj2 = {
app: {
groups: [{ name: 'name', values: 'values', id: 'name' }, { name: 'name1', values: 'values1', id: 'name1' }]
},
app2: {
groups: [{ name: 'name2', values: 'values', id: 'name2' }, { name: 'name7', values: 'values4', id: 'name7' }]
},
app3: {
groups: [{ name: 'name5', values: 'values5', id: 'name5' }, { name: 'name4', values: 'values4', id: 'name4' }]
}
};

Mutable version: If you can modify your input object, use Array.forEach() twice:
const obj = {
app: {
groups: [{ name: 'name', values: 'values' }, { name: 'name1', values: 'values1' }]
},
app2: {
groups: [{ name: 'name2', values: 'values' }, { name: 'name2', values: 'values4' }]
},
app3: {
groups: [{ name: 'name5', values: 'values5' }, { name: 'name4', values: 'values4' }]
}
};
Object.keys(obj).forEach(key => {
obj[key].groups.forEach(x => x.id = x.name);
});
console.log(obj);
Immutable version: If you don't want to modify your input object, use Array.reduce() and the spread operator to copy properties from the inner objects:
const obj = {
app: {
groups: [{ name: 'name', values: 'values' }, { name: 'name1', values: 'values1' }]
},
app2: {
groups: [{ name: 'name2', values: 'values' }, { name: 'name2', values: 'values4' }]
},
app3: {
groups: [{ name: 'name5', values: 'values5' }, { name: 'name4', values: 'values4' }]
}
};
const result = Object.entries(obj).reduce((acc, [key, val]) => {
acc[key] = { groups: val.groups.map(x => ({ ...x, id: x.name })) };
return acc;
}, {});
console.log(result);
In both cases, you'll need to iterate over the keys using Object.keys() or directly over the entries with Object.entries().

Loop through your object and then loop through the array in your inner object:
const obj = {
app: {
groups: [{ name: 'name', values: 'values' }, { name: 'name1', values: 'values1' }]
},
app2: {
groups: [{ name: 'name2', values: 'values' }, { name: 'name2', values: 'values4' }]
},
app3: {
groups: [{ name: 'name5', values: 'values5' }, { name: 'name4', values: 'values4' }]
}
};
for (app in obj) {
obj[app].groups.forEach(innerObj => {
innerObj.id = innerObj.name;
});
}
console.log(obj);

Iterate over Object.keys and use map like so:
const obj = {
app: {
groups: [{ name: 'name', values: 'values' }, { name: 'name1', values: 'values1' }]
},
app2: {
groups: [{ name: 'name2', values: 'values' }, { name: 'name2', values: 'values4' }]
},
app3: {
groups: [{ name: 'name5', values: 'values5' }, { name: 'name4', values: 'values4' }]
}
};
function addIdProp(object) {
let result = object;
Object.keys(result).forEach(key => {
result[key].groups = result[key].groups.map(({ name, values }) => { return { name, values, id: name}});
});
return result;
}
const obj2 = addIdProp(obj);
console.log(obj2);
.as-console-wrapper { max-height: 100% !important; top: 0 }
ES5 syntax:
var obj = {
app: {
groups: [{ name: 'name', values: 'values' }, { name: 'name1', values: 'values1' }]
},
app2: {
groups: [{ name: 'name2', values: 'values' }, { name: 'name2', values: 'values4' }]
},
app3: {
groups: [{ name: 'name5', values: 'values5' }, { name: 'name4', values: 'values4' }]
}
};
function addIdProp(object) {
var result = object;
Object.keys(result).forEach(function(key) {
result[key].groups = result[key].groups.map(function({ name, values }) { return { name: name, values: values, id: name}});
});
return result;
}
var obj2 = addIdProp(obj);
console.log(obj2);
.as-console-wrapper { max-height: 100% !important; top: 0 }

What about with this?
const obj = {
app: {
groups: [{ name: 'name', values: 'values' }, { name: 'name1', values: 'values1' }]
},
app2: {
groups: [{ name: 'name2', values: 'values' }, { name: 'name2', values: 'values4' }]
},
app3: {
groups: [{ name: 'name5', values: 'values5' }, { name: 'name4', values: 'values4' }]
}
};
for (let k in obj) {
if (obj.hasOwnProperty(k)) {
obj[k].groups = obj[k].groups.map((g) => {
return { ...g, id: g.name}
})
}
}
console.log(obj);

Loop through the object properties and add their group array a id prop assigning the relevant name with two nested forEaches as follows:
const obj = {
app: {
groups: [{
name: 'name',
values: 'values'
}, {
name: 'name1',
values: 'values1'
}]
},
app2: {
groups: [{
name: 'name2',
values: 'values'
}, {
name: 'name2',
values: 'values4'
}]
},
app3: {
groups: [{
name: 'name5',
values: 'values5'
}, {
name: 'name4',
values: 'values4'
}]
}
};
Object.keys(obj).forEach(e => obj[e].groups.forEach(el => el.id = el.name));
console.log(JSON.stringify(obj))
Note that it does this implementation does not create a new object, instead modifies the initial one. Your use case may welcome or discourage it.

You can try with for..in and forEach
const obj = {
app: {
groups: [{ name: 'name', values: 'values' }, { name: 'name1', values: 'values1' }]
},
app2: {
groups: [{ name: 'name2', values: 'values' }, { name: 'name2', values: 'values4' }]
},
app3: {
groups: [{ name: 'name5', values: 'values5' }, { name: 'name4', values: 'values4' }]
}
};
for (let item in obj) {
obj[item].groups.forEach(o => o.id = o.name)
}
console.log(obj)

One solution that is purely function, immutable, and independent of scope/closure would be to reduce the [Object.entries()][1] of the obj into a new obj2 result like so:
const obj = {
app: {
groups: [{ name: 'name', values: 'values' }, { name: 'name1', values: 'values1' }]
},
app2: {
groups: [{ name: 'name2', values: 'values' }, { name: 'name2', values: 'values4' }]
},
app3: {
groups: [{ name: 'name5', values: 'values5' }, { name: 'name4', values: 'values4' }]
}
};
/* Reduce entries into a new object */
const obj2 = Object.entries(obj).reduce((newObject, [key, value]) => {
/* For each value of new object array of, map group items to include id : name property */
newObject[ key ] = { groups : value.groups.map(item => ({ ...item, id : item.name })) }
return newObject
}, {})
console.log(obj2)

You have to loop through the object first and then map inside the groups array like that:
const obj = {
app: {
groups: [{ name: 'name', values: 'values' }, { name: 'name1', values: 'values1'}]
},
app2: {
groups: [{ name: 'name2', values: 'values' }, { name: 'name2', values: 'values4' }]
},
app3: {
groups: [{ name: 'name5', values: 'values5' }, { name: 'name4', values: 'values4' }]
}
};
var newObj = {...obj};
for(var key in newObj){
newObj[key] = newObj[key].groups.map(item => ({...item, id: item.name}));
}
console.log(newObj); // here is your new object with id's

You can do:
const obj = {app: {groups: [{name: 'name',values: 'values'}, {name: 'name1',values: 'values1'}]},app2: {groups: [{name: 'name2',values: 'values'}, {name: 'name2',values: 'values4'}]},app3: {groups: [{name: 'name5',values: 'values5'}, {name: 'name4',values: 'values4'}]}};
const obj2 = Object.keys(obj).map(k => ({
[k]: {
groups: obj[k].groups.map(o => {
o.id = o.name;
return o;
})
}
}));
console.log(obj2);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

How to check if name matches in both items of the array

I'm trying to figure out how you would return the matching value in this example below.
const selected = [{
name: 'Colour group',
value: 'White',
}, {
name: 'Style',
value: 'Cream',
}];
const overrides = [{
facets: [{
name: "Colour group",
values: ["White"]
}]
}, {
facets: [{
test: 'name',
name: "Colour group",
values: ["White", "Cream"],
}]
}, {
facets: [{
test: 'name',
name: "Colour group",
values: ["White", "test"],
}]
}, {
facets: [{
name: "Colour group",
values: ["White"]
}, {
name: "Style",
values: ["Cream"]
}]
}, {
facets: [{
name: "Colour group",
values: ["White"]
}, {
name: "Range",
values: ["Cream"]
}]
}];
So if my selected facets were Colour group and Style I'd then need to match it to the override that also has Colour group and Style and return. Ignoring the one that has Colour group and Range.
I have a JSfiddle with my current progress:
https://jsfiddle.net/61wvubmz/53/
Ideally this will then check if the values are the same and return the override object.
The expected return would be
{
facets: [{
name: "Colour group",
values: ["White"]
}, {
name: "Style",
values: ["Cream"]
}]
}
from the override array
const lookfor = selected.map((val) => val.name);
const facets = overrides.filter((o) => {
let compatible = true;
lookfor.forEach((lf) => {
if(!o.facets.find((of) => of.name === lf)){
compatible = false
}
})
return compatible
})
console.log(facets);
https://jsfiddle.net/r5nd40z9/4/
const selected = [{
name: 'Colour group',
value: 'White',
},
{
name: 'Style',
value: 'Cream',
}
];
const overrides = [{
facets: [{
name: "Colour group",
values: ["White"]
}]
},
{
facets: [{
test: 'name',
name: "Colour group",
values: ["White", "Cream"],
}]
}, {
facets: [{
test: 'name',
name: "Colour group",
values: ["White", "test"],
}]
}, {
facets: [{
name: "Colour group",
values: ["White"]
}, {
name: "Style",
values: ["Cream"]
}]
}, {
facets: [{
name: "Colour group",
values: ["White"]
}, {
name: "Range",
values: ["Cream"]
}]
}];
let result = {}
let output = overrides.filter(o1 => !selected.some(s1 => {
let r1, r2;
r1 = o1.facets[0].name === s1.name;
(o1.facets.length > 1) ? r2 = o1.facets[1].name === s1.name : ' ';
r2 ? result = o1 : ' '
}));
console.log(result)

How to get unique array from nested object with lodash

My collection contains the following (array of objects):
[
{
id: 'id-1',
uniqueName: 'operation-level-1',
operations: [
{
name: 'operaion-1',
label: 'operation-1-label'
},
{
name: 'operaion-2',
label: 'operation-2-label'
}
]
},
{
id: 'id-2',
uniqueName: 'operation-level-2'
operations: [
{
name: 'operaion-1',
label: 'operation-1-label'
},
{
name: 'operaion-3',
label: 'operation-3-label'
}
]
}
]
I wanted to get an array of unique operation name and label as shown below
const result = [
{
name: 'operaion-1',
label: 'operation-1-label'
},
{
name: 'operaion-2',
label: 'operation-2-label'
},
{
name: 'operaion-3',
label: 'operation-3-label'
}
]
Can someone suggest the best way to achieve this, please?
This can be easily done without lodash. You can first flat the data then map it as a key value pair and then make use of Map to remove the duplicate entries:
var data=[{ id: 'id-1', uniqueName: 'operation-level-1', operations: [ { name: 'operaion-1', label: 'operation-1-label' }, { name: 'operaion-2', label: 'operation-2-label' } ] }, { id: 'id-2', uniqueName: 'operation-level-2', operations: [ { name: 'operaion-1', label: 'operation-1-label' }, { name: 'operaion-3', label: 'operation-3-label' } ] }];
var result = [...new Map(data.flatMap(({operations})=>operations).map(k=>([k.name, k]))).values()];
console.log(result);
Or if you do not want to use Map then use filter method:
var data=[{ id: 'id-1', uniqueName: 'operation-level-1', operations: [ { name: 'operaion-1', label: 'operation-1-label' }, { name: 'operaion-2', label: 'operation-2-label' } ] }, { id: 'id-2', uniqueName: 'operation-level-2', operations: [ { name: 'operaion-1', label: 'operation-1-label' }, { name: 'operaion-3', label: 'operation-3-label' } ] }];
var result = data.flatMap(({operations})=>operations).filter((val,i,self)=>self.findIndex(j=>j.name==val.name && j.label==val.label)==i);
console.log(result);
Use _.flatMap() to get a flattened array of operations, and then use _.uniqBy() to get only items with unique name:
const data=[{ id: 'id-1', uniqueName: 'operation-level-1', operations: [ { name: 'operaion-1', label: 'operation-1-label' }, { name: 'operaion-2', label: 'operation-2-label' } ] }, { id: 'id-2', uniqueName: 'operation-level-2', operations: [ { name: 'operaion-1', label: 'operation-1-label' }, { name: 'operaion-3', label: 'operation-3-label' } ] }];
const result = _.uniqBy(
_.flatMap(data, 'operations'),
'name'
);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
With lodash/fp you can generate a function using _.flow() that flattens operations, and then get the unique values by name:
const fn = _.flow(
_.flatMap('operations'),
_.uniqBy('name')
)
const data=[{ id: 'id-1', uniqueName: 'operation-level-1', operations: [ { name: 'operaion-1', label: 'operation-1-label' }, { name: 'operaion-2', label: 'operation-2-label' } ] }, { id: 'id-2', uniqueName: 'operation-level-2', operations: [ { name: 'operaion-1', label: 'operation-1-label' }, { name: 'operaion-3', label: 'operation-3-label' } ] }];
const result = fn(data);
console.log(result);
<script src='https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)'></script>
There is no need for loadash, a simple Map object, will allow you to suppress the duplicates.
const arr = [{
id: 'id-1',
uniqueName: 'operation-level-1',
operations: [{
name: 'operaion-1',
label: 'operation-1-label'
},
{
name: 'operaion-2',
label: 'operation-2-label'
}
]
},
{
id: 'id-2',
uniqueName: 'operation-level-2',
operations: [{
name: 'operaion-1',
label: 'operation-1-label'
},
{
name: 'operaion-3',
label: 'operation-3-label'
}
]
}
];
// Go thought the arr and add all the name/label into the map
// Then use Array.from to reformate the Map into the wanted format
const uniqueArr = Array.from(arr.reduce((tmp, {
operations,
}) => {
operations.forEach(({
name,
label,
}) => {
tmp.set(name, label);
});
return tmp;
}, new Map())).map(([name, label]) => ({
name,
label,
}));
console.log(uniqueArr);

Compare two arrays and add new keys based on Index of both Arrays

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)

How to fetch data from complex array objects structures?

I have such an object
data: {
dataFirst: {
Food: [ {id: 536131, name: "option1", }]
},
dataSecond: {
Autos: [{id: 678, name: 'option1'}],
Houses: [
{id: 6876, name: "option1"},
{id: 6876, name: "Placed App"},
],
Phones: [
{id: 672, name: "option1"},
{id: 97249, name: "Placed},
],
Food: [
{id: 772, name: "option1"},
{id: 6777, name: "Placed},
],
}
}
The problem is, that I may have same data in dataFirst and dataSecond, for examle 'Food', I have 2 array objects that contains different data but I need to make it one object 'Food' with the data from 2 of them, from the dataFirst 'Food' and dataSecond 'Food'. I had such a code:
export const parser = ({ data }) => {
const result = Object.values(data).reduce((prev, topicsGroup) => {
Object.assign(prev, topicsGroup);
return prev;
}, {});
return result;
}
but this code doesn't unite 2 'Food' objects but returns data only from the dataFirst 'Food' object wihout second one.
You can iterate through all values of your main data object with Object.values(data) and combine them with reduce by concatenating arrays corresponding to common keys:
let data = {
dataFirst: {
Food: [{
id: 536131,
name: "option1",
}]
},
dataSecond: {
Autos: [{
topicId: 678,
name: 'option1'
}],
Houses: [{
topicId: 6876,
name: "option1"
},
{
topicId: 6876,
topicName: "Placed App"
},
],
Phones: [{
topicId: 672,
name: "option1"
},
{
topicId: 97249,
name: "Placed"
},
],
Food: [{
topicId: 772,
name: "option1"
},
{
topicId: 6777,
name: "Placed"
},
],
}
};
let res = Object.values(data).reduce((acc, curr) => {
Object.entries(curr).forEach(([k, v]) => {
if (k in acc) acc[k] = acc[k].concat(v);
else acc[k] = v;
});
return acc;
}, {});
console.log(res);

Return a set of documents with all sub-arrays containing a given value in loopback or nodejs

How do I return a set of documents that has sub-arrays that matches common values. To better explain, consider the following data:
[
{
Category: 1,
Products: [
{
Name: 'ABC',
ColorCode:[1,2,3,4,5]
},
{
Name: 'DEF',
ColorCode:[1,2,3,4,5,6]
},
{
Name: 'GHI',
ColorCode:[1,2,3,4,6,7]
}
]
},
{
Category: 2,
Products: [
{
Name: 'JKL',
ColorCode:[4,6,7,]
},
{
Name: 'MNO',
ColorCode:[4,5,6,9,]
}
]
},
{
Category: 3,
Products: [
{
Name: 'OPQ',
ColorCode:[3,4,5,6,9,10]
},
{
Name: 'RST',
ColorCode:[2,3,5,6,9,10]
}
]
}]
The task is,
Get all the Categories with all the products containing a specific color code:
For example,
For ColorCode = 6,
Result should be:
[
{
Category: 2,
Products: [
{
Name: 'JKL',
ColorCode:[4,6,7,]
},
{
Name: 'MNO',
ColorCode:[5,6,9,]
}
]
},
{
Category: 3,
Products: [
{
Name: 'OPQ',
ColorCode:[3,4,5,6,9,10]
},
{
Name: 'RST',
ColorCode:[2,3,5,6,9,10]
}
]
}]
For ColorCode = 4,
Result should be:
[
{
Category: 1,
Products: [
{
Name: 'ABC',
ColorCode:[1,2,3,4,5]
},
{
Name: 'DEF',
ColorCode:[1,2,3,4,5,6]
},
{
Name: 'GHI',
ColorCode:[1,2,3,4,6,7]
}
]
},
{
Category: 2,
Products: [
{
Name: 'JKL',
ColorCode:[4,6,7,]
},
{
Name: 'MNO',
ColorCode:[4,5,6,9,]
}
]
}]
For ColorCode = 7,
Result should be an empty array:
[]
Thanks in advance.
You're looking for Array.prototype.filter.
// filter out categories that don't contain color code 4
categories.filter(function(category) {
return category.products.filter(containsColor(4)) > 0;
});
function containsColor(colorCode) {
return function(product) {
return product.ColorCode.indexOf(colorCode) >= 0;
};
}

Categories

Resources