Nested JSON - Join sub-object - javascript

How can I remove sub-objects?
[{
"id": "1",
"desc": "SOME PRODUCT",
"codigo": "CODE-28",
"codigoBarras": "2000000001",
"unidade": "PCT",
"price": "24.15",
"current_inventory": [{
"2kg": "5",
"5kg": "5",
"10kg": "5",
"20kg": "5",
"productId": "1"
}]
}]
[{
"id": "1",
"desc": "SOME PRODUCT",
"codigo": "CODE-28",
"codigoBarras": "2000000001",
"unidade": "PCT",
"price": "24.15",
"current_inventory_2kg": "5",
"current_inventory_5kg": "5",
"current_inventory_10kg": "5",
"current_inventory_20kg": "5",
}]

Use Object.keys() and a forEach loop
var x =[
{
"id": "1",
"desc": "SOME PRODUCT",
"codigo": "CODE-28",
"codigoBarras": "2000000001",
"unidade": "PCT",
"price": "24.15",
"current_inventory": [
{
"2kg": "5",
"5kg": "5",
"10kg": "5",
"20kg": "5",
"productId": "1"
}
]
}
]
x[0].current_inventory.forEach(e=>{
Object.keys(e).forEach(j=>{
x[0]['current_inventory_'+j]=e[j];
})
delete x[0].current_inventory
})
console.log(x)

Use Object.entries and reduce will simplify.
const data = [
{
id: "1",
desc: "SOME PRODUCT",
codigo: "CODE-28",
codigoBarras: "2000000001",
unidade: "PCT",
price: "24.15",
current_inventory: [
{
"2kg": 5,
"5kg": 5,
"10kg": 5,
"20kg": 5,
productId: 1
}
]
}
];
const [first] = data;
const updated = Object.entries(first).reduce((acc, [key, value]) => {
if (Array.isArray(value)) {
value.forEach(item =>
Object.entries(item).forEach(
([cKey, cValue]) => (acc[`${key}_${cKey}`] = cValue)
)
);
} else {
acc[key] = value;
}
return acc;
}, {});
console.log(updated);

THANK YOU VERY MUCH!!!
Solved using the code below:
data is de object
estoqueFracionado is the sub-object
for (let [key, value] of Object.entries(data)) {
value.estoqueFracionado.forEach (e => {
Object.keys(e).forEach(j => {
value['estoqueFracionado_' + j] = e[j]
})
delete value.estoqueFracionado
})
}

Related

How to convert flat data to hierarchical JSON?

I use a fake api with this json, I still haven't been able to with this function, I need to convert the structure to look like this and I need to convert this data and then unconvert when saving
so that I change the parameters blockId to id, blockParent to parent.
{
"blocks": [
{
"blockId": "12",
"name": "Sierra",
"abrv": "Sir",
"blockParent": "0"
},
{
"blockId": "23",
"name": "Velasco",
"abrv": "Vel",
"blockParent": "12"
},
{
"blockId": "32",
"name": "UnitOne",
"abrv": "Uni",
"blockParent": "23"
},
{
"blockId": "48",
"name": "Vani",
"abrv": "Van",
"blockParent": "12"
},
{
"blockId": "57",
"name": "UnitTwo",
"abrv": "UniTwo",
"blockParent": "48"
}
]
}
const flatToTree = (blocks: IListBlocks[]) => {
const array: IListBlocks[] = []
const children: IListBlocks[] = []
blocks.forEach((block) => {
if (block.blockParent === block.blockId) {
array.push(block)
} else {
children.push(block)
}
})
array.forEach((block) => {
block.children = children.filter(
(child) => child.blockParent === block.blockId,
)
})
return array
}
{
"id": "12",
"title": "Sierra",
"subtitle": "Sir",
"parent": "0",
"children": [
{
"id": "13",
"title": "Sierra",
"subtitle": "Sir",
"parent": "12",
}
]
}

change the value of object inside a list

My code's output is like this:
let myArray = [{"num": "2", "name": "Jhon"}, {"num": "1", "name": "Sara"}, {"num": "2", "name": "Domnic"}, {"num": "3", "name": "Bravo"}]
How can I access value of num in each field of the list and if num: 2, change its value to 5?
Use Array.forEach to change the original Array
let myArray = [{ "num": "2", "name": "Jhon" }, { "num": "1", "name": "Sara" }, { "num": "2", "name": "Domnic" }, { "num": "3", "name": "Bravo" }]
myArray.forEach((node) => node.num = node.num == "2" ? "5" : node.num);
console.log(myArray);
If you want to create a new array from the existing one, Use Array.map
let myArray = [{ "num": "2", "name": "Jhon" }, { "num": "1", "name": "Sara" }, { "num": "2", "name": "Domnic" }, { "num": "3", "name": "Bravo" }]
const newArray = myArray.map(({ ...node }) => node.num = node.num == "2" ? "5" : node.num);
console.log(newArray);
Please Note: Do not forget to use spread syntax ({ ...node }) else your original array will be modified here.
You could use array map:
let myArray = [{
"num": "2",
"name": "Jhon"
}, {
"num": "1",
"name": "Sara"
}, {
"num": "2",
"name": "Domnic"
}, {
"num": "3",
"name": "Bravo"
}]
const result = myArray.map(({...item}) => {
if (item.num == 2)
item.num = "5"
return item
})
console.log(result)

Filter an array of objects by another object of filters

I have an array of objects who follow this structure below:
{
"level": 1
"objectId": "3756"
"objectIdNo": 35636
"wpId": "3635473"
}
I now want to filter an array of these objects by another object. This filterObject would have the structure below:
// filterObject
{
level: "2"
objectId: "10"
wpId: "1"
}
But this filterObject doesn't always have all the key-value pairs because they get set manually in the UI. As a result the filterObject can also look like this:
{
level: "2"
}
My goal is to return a new array of filteredObjects who match this filterObject. When only one filter exists on the filterObject I want to return all objects that match this one key-value pair. But if more filters exist on the filterObject I want to return all objects that match both key-value pairs (not only one).
Example:
This is the data I want to filter:
[
{
"level": "1"
"objectId": "11"
"objectIdNo": "320"
"wpId": "123"
},
{
"level": "2"
"objectId": "12"
"objectIdNo": "321"
"wpId": "123"
},
{
"level": "2"
"objectId": "13"
"objectIdNo": "322"
"wpId": "120"
},
]
1.
If this is my filterObject:
{
"level": "2"
}
Return:
[
{
"level": "2"
"objectId": "12"
"objectIdNo": "321"
"wpId": "123"
},
{
"level": "2"
"objectId": "13"
"objectIdNo": "322"
"wpId": "120"
},
]
2.
If this is my filterObject:
{
"level": "2",
"wpId": "123"
}
Return:
[
{
"level": "2"
"objectId": "12"
"objectIdNo": "321"
"wpId": "123"
},
]
I hope that explains the logic I want to achieve which I couldn't implement myself. I would appreciate some ideas or applicable functions.
This is what I already tried in React. The data variable holds the array of objects and the filter variable hold the filterObjects.
useEffect(() => {
if (data) {
const filtered = data.filter((task) => {
if (!filter) {
return true;
}
return (
task.level === filter.level ||
task.objectId === filter.objectId ||
task.wpId === filter.wpId
);
});
setFilteredTasks(filtered);
}
}, [filter]);
With my attempt, if I just set the one filter key-value pair I get an empty array,
You can achieve this result using filter, Object.keys, and every.
You have to use filter and pass predicate that tell whether it is included in the final result.
In predicate, loop over all properties on the filters object and match if it is present in data or not. Simple
data.filter((o) =>Object.keys(filters).every((k) => filters[k] === o[k]));
const data = [{
level: "1",
objectId: "11",
objectIdNo: "320",
wpId: "123",
},
{
level: "2",
objectId: "12",
objectIdNo: "321",
wpId: "123",
},
{
level: "2",
objectId: "13",
objectIdNo: "322",
wpId: "120",
},
];
const filters = {
level: "2",
wpId: "123",
};
const result = data.filter((o) =>
Object.keys(filters).every((k) => filters[k] === o[k])
);
console.log(result);
This should do the trick!
const exampleData = [
{
"level": "1",
"objectId": "11",
"objectIdNo": "320",
"wpId": "123",
},
{
"level": "2",
"objectId": "12",
"objectIdNo": "321",
"wpId": "123",
},
{
"level": "2",
"objectId": "13",
"objectIdNo": "322",
"wpId": "120",
},
];
const filterObject1 = {
"level": "2",
}
const filterObject2 = {
"level": "2",
"wpId": "123"
}
function filter(data, filterObject) {
const filterValues = Object.entries(filterObject)
let filteredData = data
for(const [filterKey, filterValue] of filterValues) {
filteredData = filteredData.filter(obj => obj[filterKey] === filterValue)
}
return filteredData
}
console.log(filter(exampleData, filterObject1))
console.log(filter(exampleData, filterObject2))
You can do like this:
const data = [
{
level: "1",
objectId: "11",
objectIdNo: "320",
wpId: "123",
},
{
level: "2",
objectId: "12",
objectIdNo: "321",
wpId: "123",
},
{
level: "2",
objectId: "13",
objectIdNo: "322",
wpId: "120",
},
];
const filterObject = {
level: "2",
wpId: "123",
};
const result = data.filter((item) => {
let flag = true;
Object.keys(filterObject).forEach((key) => {
if (item[key] !== filterObject[key]) {
flag = false;
return;
}
});
return flag;
});
console.log(result);
const input = [ { "level": "1", "objectId": "11", "objectIdNo": "320", "wpId": "123" }, { "level": "2", "objectId": "12", "objectIdNo": "321", "wpId": "123", }, { "level": "2", "objectId": "13", "objectIdNo": "322", "wpId": "120" }, ]
const filter = { "level": "2", "wpId": "123" };
const filteredOutput = input.filter( obj => {
return Object.keys(filter).every( filterKeys => {
return obj[filterKeys] === filter[filterKeys]
});
});
console.log(filteredOutput);

How to filter and grouped by id nested data in javascript?

I have JSON data which has structure as follows:
const SubSpecs= [
{
"_id": "1",
"nom": "installation",
"blocks": [
{
"idBlock": "1",
"ArtisanOffres": [
{
"idArtisan": "1",
"price": 12
}
]
},
{
"idBlock": "2",
"ArtisanOffres": [
{
"idArtisan": "1",
"price": 14
}
]
}
]
},
{
"_id": "2",
"nom": "tech",
"blocks": [
{
"idBlock": "1",
"ArtisanOffres": [
{
"idArtisan": "1",
"price": 12
}
]
},
{
"idBlock": "2",
"ArtisanOffres": [
{
"idArtisan": "1",
"price": 14
},
{
"idArtisan": "2",
"price": 50
}
]
}
]
}
],
}
this is the array of artisans that i want to filtered by its id's:
artisans= [
{
"_id": "1",
"username": "test1"
},
{
"_id": "2",
"username": "test2"
}
]
now i want to extract all prices that have the same id of artisan ( extract by id) and grouped by this id !!
i just start a simple function but i didn't find the way to finish it !!
can anyone help please !!
I am not able to understand how to filter such data ? Below code doesn't work I am not able to find any example of such filtering.
this is my function:
const total = data
.map((fb) =>
fb.blocks
.map((b) =>
b.ArtisanOffres.map((ao)=> ao.price)
.join(",")
.includes("1")
)
.join(",")
)
.join(",")
.split(",");
i'm new in javascript and i face this algorithm problem,
Ciao, what do you think about this solution? I filtered your data by idArtisan === "1", then sum all the prices. Result is 52. Here working example:
const SubSpecs= [
{
"_id": "1",
"nom": "installation",
"blocks": [
{
"idBlock": "1",
"ArtisanOffres": [
{
"idArtisan": "1",
"price": 12
}
]
},
{
"idBlock": "2",
"ArtisanOffres": [
{
"idArtisan": "1",
"price": 14
}
]
}
]
},
{
"_id": "2",
"nom": "tech",
"blocks": [
{
"idBlock": "1",
"ArtisanOffres": [
{
"idArtisan": "1",
"price": 12
}
]
},
{
"idBlock": "2",
"ArtisanOffres": [
{
"idArtisan": "1",
"price": 14
},
{
"idArtisan": "2",
"price": 50
}
]
}
]
}
];
let result = SubSpecs.map(sub => {
return sub.blocks.map(block => {
return block.ArtisanOffres.filter(artisan => artisan.idArtisan === "1");
});
});
let array = result.flat(2);
let final_sum = {};
final_sum.idArtisan = "1";
final_sum.total = array.reduce(function(_this, val) {
return _this + val.price
}, 0);
console.log(final_sum);
Explanation: Used 2 maps (because SubSpecs and blocks are arrays) then a filter for idArtisan. result.flat(2) is because maps result creates a 3-level array. Finally a reducer to sum prices.

sorting json tree with multiple property

i have prepared a json tree from a plain json. But i need to sort the tree with multiple conditions.
for example at level 1 we have multiple objects. we need to sort with level and then with a name property.
level is a number and name is an alphanumeric. so name sorting is alphabets first and then numbers
Below is the input json
var inputJson = [
{
"level": "1",
"leafFlag": "1",
"path":"p123",
"name":"food23"
},
{
"level": "1",
"leafFlag": "1",
"path":"r125",
"name":"car1"
},
{
"level": "2",
"leafFlag": "0",
"path":"p123/p345",
"name":"apple345"
},
{
"level": "2",
"leafFlag": "1",
"path":"p123/p095",
"name":"123banana"
},
{
"level": "3",
"leafFlag": "0",
"path":"p123/p095/p546",
"name":"543"
},
{
"level": "2",
"leafFlag": "1",
"path":"r125/yhes",
"name":"tata78"
}
]
var output = [];
The below code prepares the json tree.
I tried here for sorting with multiple properties
inputJson = inputJson.sort((a, b) => (parseInt(a.level) > parseInt(b.level)) ? 1 : -1)
inputJson.forEach(v => {
if (v.level == "1") {
v.children = [];
output.push(v);
}
else {
pathValues = v.path.split("/");
pathValues.pop();
var node = null;
var fullPath = "";
pathValues.forEach(p => {
fullPath = fullPath === "" ? p : fullPath + "/" + p;
node = (node == null ? output : node.children).find(o => o.path === fullPath);
})
node.children = node.children || [];
node.children.push(v);
}
})
Output from above:
var output = [
{
"level": "1",
"leafFlag": "1",
"path": "p123",
"name": "food23",
"children": [
{
"level": "2",
"leafFlag": "0",
"path": "p123/p345",
"name": "apple"
},
{
"level": "2",
"leafFlag": "1",
"path": "p123/p095",
"name": "banana",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "p123/p095/p546",
"name": "grapes"
}
]
}
]
},
{
"level": "1",
"leafFlag": "1",
"path": "r125",
"name": "car",
"children": [
{
"level": "2",
"leafFlag": "1",
"path": "r125/yhes",
"name": "tata",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "r125/yhes/sdie",
"name": "Range Rover"
}
]
},
{
"level": "2",
"leafFlag": "0",
"path": "r125/theys",
"name": "suzuki"
}
]
}
]
Expected output:
[
{
"level": "1",
"leafFlag": "1",
"path": "r125",
"name": "car",
"children": [
{
"level": "2",
"leafFlag": "0",
"path": "r125/theys",
"name": "suzuki"
},
{
"level": "2",
"leafFlag": "1",
"path": "r125/yhes",
"name": "tata",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "r125/yhes/sdie",
"name": "Range Rover"
}
]
}
]
},
{
"level": "1",
"leafFlag": "1",
"path": "p123",
"name": "food",
"children": [
{
"level": "2",
"leafFlag": "0",
"path": "p123/p345",
"name": "apple"
},
{
"level": "2",
"leafFlag": "1",
"path": "p123/p095",
"name": "banana",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "p123/p095/p546",
"name": "grapes"
}
]
}
]
}
]
I tried something like below
inputJson = inputJson.sort((a, b) => (parseInt(a.level) > parseInt(b.level)) ? 1 : -1 && a.name > b.name ? 1 ? -1)
You could take a single sort by sorting levels first and then by name.
.sort((a, b) => a.level - b.level || a.name.localeCompare(b.name))
Then build the tree with the sorted items.
var data = [{ level: "1", leafFlag: "1", path: "p123", name: "food" }, { level: "1", leafFlag: "1", path: "r125", name: "car" }, { level: "2", leafFlag: "0", path: "p123/p345", name: "apple" }, { level: "2", leafFlag: "1", path: "p123/p095", name: "banana" }, { level: "3", leafFlag: "0", path: "p123/p095/p546", name: "grapes" }, { level: "2", leafFlag: "1", path: "r125/yhes", name: "tata" }],
result = data
.sort((a, b) => a.level - b.level || a.name.localeCompare(b.name))
.reduce((r, o) => {
let p = o.path.split('/');
p.pop();
let target = p.reduce((t, _, i, p) => {
var path = p.slice(0, i + 1).join('/'),
temp = (t.children = t.children || []).find(q => q.path === path);
if (!temp) t.children.push(temp = { path }); // this is not necessary
// if all nodes are given
return temp;
}, { children: r });
(target.children = target.children || []).push({ ...o });
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
var rootes= inputJson.filter(x=>x.level=='1')
for(i=0;i<rootes.length;i++){
rootes[i].children=[] }
var objwithchild = inputJson.filter(x=>x.leafFlag=='1')
for(i=0;i<objwithchild.length;i++){
objwithchild[i].children=[] }
inputJson.forEach(x=>{
patharr=x.path.split('/')
path=patharr.pop()
switch (x.level) {
case '2':
rootes.filter(p=>{if(p.path==patharr[0]){p.children.push(x)}
})
break
case '3':
objwithchild.filter(p=>{if(p.path==patharr[0]+'/'+patharr[1]){p.children.push(x)}
})
break
}
})
console.dir(rootes,{depth:null})
You should first sort by name, then re-sort the sorted array by level.
inputJson = inputJson.sort((a,b) => {return a.name > b.name}).sort((a,b) => {return (Number(a.level) - Number(b.level)};

Categories

Resources