Lodash extract value from nested object - javascript

I have below object which I am currently looping through to get item value. Currently I am using lodash _.forEach to achieve this. I am not sure what is best possible to create a new object with item name as key and value as value.
data = [
{
"panels" : [
{
"title": "Panel 1",
"items" : [
{
"name": item1,
"value": 1
}
{
"name": item2,
"value": 2
}
]
},
{
"title": "Panel 2",
"items" : [
{
"name": item3,
"value": 3
}
{
"name": item4,
"value": 5
}
]
}
]
}
{
"panels" : [
{
"title": "Panel 3"
"items" : [
{
"name": item5,
"value": 5
}
{
"name": item6,
"value": 6
}
]
}
]
}
]
let values = [];
_.forEach(data, (groups) => {
_.forEach(groups.panels, (panel) => {
_.forEach(panel.items, (item) => {
values[item.name] = item.value;
});
});
});
return values;
Is there any other way I can achieve this in more efficient way ?

You could use a nested for...of loops with destructuring
const data=[{panels:[{title:"Panel 1",items:[{name:"item1",value:1},{name:"item2",value:2}]},{title:"Panel 2",items:[{name:"item3",value:3},{name:"item4",value:5}]}]},{panels:[{title:"Panel 3",items:[{name:"item5",value:5},{name:"item6",value:6}]}]}];
const output = {};
for (const { panels } of data)
for (const { items } of panels)
for (const { name, value } of items)
output[name] = value;
console.log(output)
Or,
You could use a chained flatMap to get an array of items. Then reduce the items array to get an object with name as key and value as it's value
const data=[{panels:[{title:"Panel 1",items:[{name:"item1",value:1},{name:"item2",value:2}]},{title:"Panel 2",items:[{name:"item3",value:3},{name:"item4",value:5}]}]},{panels:[{title:"Panel 3",items:[{name:"item5",value:5},{name:"item6",value:6}]}]}];
const output = data.flatMap(o => o.panels)
.flatMap(p => p.items)
.reduce((acc, o) => ({ ...acc, [o.name]: o.value }), {})
console.log(output)

Related

nested filter array javascript

I want to create a nested filter in js
when I filter my array primary data is affected and changed but I need preliminary data to remove filters
my js code :
let result = companies;
result.map((item, i) => {212
let rows = [...result[i].table.table_rows].filter((item3) => {
return Object.keys(item3).some(i => item3[i][key] === value[key]);
});
result[i].table.table_rows = [...rows];
return result[i];
});
arrayFilter(result);
my data is:
{
"companies": [
{
"company": {
"name": "company 1"
},
"table": {
"table_rows": [
{
"cells": {
"product_name": "prod1",
"pa_size": "12"
}
},
{
"cells": {
"product_name": "prod2",
"pa_size": "15"
}
}
]
}
},
{
"company": {
"name": "company 2"
},
"table": {
"table_rows": [
{
"cells": {
"product_name": "prod2-1",
"pa_size": "12"
}
},
{
"cells": {
"product_name": "prod2-2",
"pa_size": "18"
}
}
]
}
}
]
}
I tried many ways to solve this problem, but I did not get the right answer
Your question is not clear, the point I have understand that you wanted to filter the array "table_rows" located inside each companies array object? map and filter returns new array, so the solution for this is:
result = result.companies.map((item, i) => {
const newItem = {...item};
let rows = newItem .table.table_rows.filter((item3) => {
return Object.keys(item3).some(i => item3[i][key] === value[key]);
});
newItem.table_rows = [...rows];
return newItem ;
});
arrayFilter(result);

Lodash deep filter and map nested object

I have below object which I am currently looping through in number of different functions to get an item with name or setting a new value. Currently I am using lodash _.foreach and ._map to achieve both actions. I know lodash has function such as _.filter however I am unable to get it to work with the object that I have.
let data = [
{
"panels" : [
{
"title": "Panel 1",
"items" : [
{
"name": item1,
"value": 1
}
{
"name": item2,
"value": 2
}
]
},
{
"title": "Panel 2",
"items" : [
{
"name": item3,
"value": 3
}
{
"name": item4,
"value": 5
}
]
}
]
}
{
"panels" : [
{
"title": "Panel 3"
"items" : [
{
"name": item5,
"value": 5
}
{
"name": item6,
"value": 6
}
]
}
]
}
{
"panels" : [
{
"title": "Panel 4"
"items" : [
{
"name": item7,
"value": 7
}
{
"name": item8,
"value": 8
}
]
}
]
}
]
// Get item from the object with given name
getItem: function(name) {
let item = false;
_.forEach(data, function (group) {
_.forEach(group.panels, function (panel) {
_.forEach(panel.items, function (item) {
if (item.name == name) {
filterItem = item;
return false;
}
});
});
});
return item ;
},
//Set item new value
updateItemValue (name, value) {
_.map(data, function(group) {
_.map(group.panels, function(panel) {
_.map(panel.items, function(item) {
if( item.name === name ) {
item.value = value;
}
});
});
});
}
Is there any other way I can achieve this in more efficient way ?
You could use nested for...of loops with destructuring. If an item has the provided name, return the item. Apply the same approach to updateItemValue as well
const data=[{panels:[{title:"Panel 1",items:[{name:"item1",value:1},{name:"item2",value:2}]},{title:"Panel 2",items:[{name:"item3",value:3},{name:"item4",value:4}]}]},{panels:[{title:"Panel 3",items:[{name:"item5",value:5},{name:"item6",value:6}]}]}];
function getItem(name) {
for (const { panels } of data)
for (const { items } of panels)
for (const o of items)
if (o.name === name)
return o
return; // if no match is found
}
function updateItemValue(name, value) {
for (const { panels } of data)
for (const { items } of panels)
for (const o of items)
if (o.name === name) {
o.value = value
return;
}
}
console.log(getItem('item1'))
console.log(getItem('item2'))
console.log(getItem('doesntexist'))
updateItemValue('item3', 33) // update the value
console.log(getItem('item3')) // gets the updated value

Get some data from nested object

I have this nested object (json):
const json = {
"application": {
"App1": {
"cats": [
1
]
},
"App2": {
"cats": [
3
]
},
"App3": {
"cats": [
1,
2
]
}
},
"categories": {
"1": {
"name": "FirstCategory"
},
"2": {
"name": "SecondCategory"
},
"3": {
"name": "ThirdCategory"
}
}
};
This object has two main properties: application and categories.
I want to map over application's cats array and get name property of each element of cats array.
So the final result should look like:
{
"App1": "FirstCategory",
"App2": "ThirdCategory",
"App3": "FirstCategory, ThirdCategory"
}
I have tried to use map function, but the main difficulty is that inside applicaiton property cats is array (can have multiple values). So the code below didn't work:
Object.values(json.application).map(val => {
Object.keys(json.categories).map(key => {
//print something
});
});
You can use Array.reduce for an elegant solution.
const json = {
"application": {
"App1": {
"cats": [
1
]
},
"App2": {
"cats": [
3
]
},
"App3": {
"cats": [
1,
2
]
}
},
"categories": {
"1": {
"name": "FirstCategory"
},
"2": {
"name": "SecondCategory"
},
"3": {
"name": "ThirdCategory"
}
}
};
//Getting Application object
const application = json.application
//Getting Categories object
const categories = json.categories
//initializing reduce with a blank object and pushing all the keys of the application object
//Looping over keys of application object
const requiredOutput = Object.keys(application).reduce((out, appKey) => {
//Setting value based on categories name
out[appKey] = application[appKey].cats.map(id => categories[id].name)
return out
}, {})
console.log(requiredOutput)
PS: You can refer this gist for safe reading from a nested object.
Try it with this.
for(let val in json.application){
json.application[val] = json.application[val].cats.map(cat => json.categories[cat].name).join(",")
}
const result = Object.keys(json.application).reduce((a,key) => {
a[key] = json.application[key].cats
.map(cat => json.categories[cat].name)
.join(", ")
return a;
}, {})
loop over keys of application
for each key loop over car, and for each cat return string value from category
join list of cat strings

Merging an array of objects without overwriting

I am currently with some JSON, which has to be structured in a tree-like hierarchy. The depth of the hierarchy varies a lot, and is therefor unknown.
As it is right now, I have achieved to get an array of objects. Example is below.
[
{
"name": "level1",
"collapsed": true,
"children": [
{
"name": "Level 1 item here",
"id": 360082134191
}
]
},
{
"name": "level1",
"collapsed": true,
"children": [
{
"name": "level2",
"collapsed": true,
"children": [
{
"name": "Level 2 item here",
"id": 360082134751
}
]
}
]
},
{
"name": "level1",
"collapsed": true,
"children": [
{
"name": "Another level 1 item",
"id": 360082262772
}
]
}
]
What I want to achieve is these objects to be merged, without overwriting or replacing anything. Listed below is an example of how I want the data formatted:
[
{
"name": "level1",
"collapsed": true,
"children": [
{
"name": "level2",
"collapsed": true,
"children": [
{
"name": "Level 2 item here",
"id": 360082134751
}
]
},
{
"name": "Level 1 item here",
"id": 360082134191
},
{
"name": "Another level 1 item",
"id": 360082262772
}
]
}
]
How would I achieve this with JavaScript? No libraries is preferred, ES6 can be used though.
Edit:
It is important that the output is an array, since items without children can appear at the root.
I am assuming you need a little help on working with the data. There could be multiple ways to achieve this, here is how would I do.
// data => supplied data
const result = data.reduce ((acc, item) => {
// if acc array already contains an object with same name,
// as current element [item], merfe the children
let existingItem;
// Using a for loop here to create a reference to the
// existing item, so it'd update this item when childrens
// will be merged.
for (let index = 0; index < acc.length; index ++) {
if (acc[index].name === item.name) {
existingItem = acc[index];
break;
}
}
// if existingItem exists, merge children of
// existing item and current item.
// else push it into the accumulator
if (existingItem) {
existingItem.children = existingItem.children.concat(item.children);
} else {
acc.push (item);
}
return acc;
}, []);
I'm assuming you want to group based on the name property in the level 1 object. You could do a simple reduce and Object.values like this:
const input = [{"name":"level1","collapsed":true,"children":[{"name":"Level 1 item here","id":360082134191}]},{"name":"level1","collapsed":true,"children":[{"name":"level2","collapsed":true,"children":[{"name":"Level 2 item here","id":360082134751}]}]},{"name":"level1","collapsed":true,"children":[{"name":"Another level 1 item","id":360082262772}]}]
const merged = input.reduce((r,{name, collapsed, children}) =>{
r[name] = r[name] || {name, collapsed, children:[]};
r[name]["children"].push(...children)
return r;
}, {})
const final = Object.values(merged);
console.log(final)
You could do the whole thing in one line:
const input = [{"name":"level1","collapsed":true,"children":[{"name":"Level 1 item here","id":360082134191}]},{"name":"level1","collapsed":true,"children":[{"name":"level2","collapsed":true,"children":[{"name":"Level 2 item here","id":360082134751}]}]},{"name":"level1","collapsed":true,"children":[{"name":"Another level 1 item","id":360082262772}]}]
const output = Object.values(input.reduce((r,{name,collapsed,children}) => (
(r[name] = r[name] || {name,collapsed,children: []})["children"].push(...children), r), {}))
console.log(output)

React Native - get value of json depending on dynamic state

I have a json getting from API and store it into this.state.data like :
[
{
"name": "Primary Category",
"value": [
{
"value": "Fracture",
"Diagnosis_Code": ["DIAG003"],
"name": "Primary Category",
"FK_Diagnosis_Content_ID": 3,
"FK_Diagnosis_Category_ID": 1
},
{
"value": "Osteoarthritis",
"Diagnosis_Code": ["DIAG001"],
"name": "Primary Category",
"FK_Diagnosis_Content_ID": 1,
"FK_Diagnosis_Category_ID": 1
},
{
"value": "Osteonecrosis",
"Diagnosis_Code": ["DIAG002", "DIAG004"],
"name": "Primary Category",
"FK_Diagnosis_Content_ID": 2,
"FK_Diagnosis_Category_ID": 1
},
]
},
{
"name": "Anatomy",
"value": [
{
"value": "Hip",
"Diagnosis_Code": ["DIAG001"],
"name": "Anatomy",
"FK_Diagnosis_Content_ID": 4,
"FK_Diagnosis_Category_ID": 2
},
{
"value": "Pelvis",
"Diagnosis_Code": ["DIAG002", "DIAG003", "DIAG004"],
"name": "Anatomy",
"FK_Diagnosis_Content_ID": 6,
"FK_Diagnosis_Category_ID": 2
}
]
}
]
and I have a dynamic state using a function like this:
onChangeTextPress(key, value){
this.state.selected[key] = value
//another code
}
the example of this.state.selected is
[ 'Primary Category': 'Fracture', Anatomy: 'Hip']
I want to get FK_Diagnosis_Content_ID json depending on which this.state.selected[key] and it's value filled
so depending of selected example, I will have a result: [3, 4]
because json have a key called name and the value is Primary Category, and the value of selected state Primary Category is Fracture so I have a value of FK_Diagnosis_Content_ID in json, likewise about the Anatomy: 'Hip'
I don't know if you all know what I want, but feel free to asking me if you need another information,
hope someone can help me
You can get use of Object.keys() and Array.prototype.includes().
Sample 1
// Let's assume you have the below structure
const data = { 'Primary Category': 'Fracture', Anatomy: 'Hip' }
Object.keys(data).forEach((key) => console.log(key))
// Output:
// Primary Category
// Anatomy
So to get the desired value you can use something like below
Sample 2
// this.state.selected => { 'Primary Category': 'Fracture', Anatomy: 'Hip' }
const keys = Object.keys(this.state.selected);
const result = [];
this.state.data.forEach((d) => {
if(keys.includes(d.name)) {
d.value.forEach((v) => {
if(v.value === this.state.selected[d.name]) {
result.push(v['FK_Diagnosis_Content_ID']);
}
})
}
});
console.log(result);
// Output: [3,4]
Sample 3
// this.state.selected => [{ 'Primary Category': 'Fracture'}, {Anatomy: 'Hip' }]
// Since we know there is only one key in every object
const keys = this.state.selected.map((s) => Object.keys(s)[0])
const result = [];
this.state.data.forEach((d) => {
if(keys.includes(d.name)) {
d.value.forEach((v) => {
if(v.value === this.state.selected[keys.indexOf(d.name)][d.name]) {
result.push(v['FK_Diagnosis_Content_ID']);
}
})
}
});
console.log(result);
// Output: [3,4]
You can use this just as
const key = Object.keys(this.state.selected);
const response = [];
this.state.data.forEach((d) => {
if(key.includes(d.tag)) {
d.value.forEach((v) => {
if(v.value === this.state.selected[d.name]) {
result.push(v['FK_Diagnosis_Content_ID']);
}
})
}
});
console.log(result);

Categories

Resources