How can i change the organization of my json? - javascript

Hey i tried to transform a json file (as a js object but I can not do it). Here is an example of my problem:
Input object
{
"peoples": [
{
"name": "Alain",
"nationality": "Italian"
},
{
"name": "John",
"nationality": "French"
},
{
"name": "FOO",
"nationality": "French"
}
]
}
Output object
{
"nationality": {
"french": {
"peoples": [{ "name": "John" }, { "name": "FOO" }]
},
"italian": {
"peoples": [{ "name": "Alain" }]
}
}
}
How can i do this ? maybe Lodash but i have not find any way to do this. Can anyone help me ?

You can use a simple reduce:
const obj = {
"peoples": [{
"name": "Alain",
"nationality": "Italian"
},
{
"name": "John",
"nationality": "French"
},
{
"name": "FOO",
"nationality": "French"
}
]
}
const output = obj.peoples.reduce((a, {nationality: n, ...rest}) => {
const x = a.nationality[n]
if (x) x.push(rest)
else a.nationality[n] = [rest]
return a
}, { nationality: {} })
console.log(output)
Note, I've used a spread operator to get the rest of the properties, so if you were to add more properties to each person, then those would be included in the new object.

Related

Grouping array nested value while comparing 2 objects

I am working in small react project & I am facing issue in grouping the data. Requirement is to group the id & its feature into a single row if same id is there in before & after object.
Json Data:
{
"before":{
"device": [
{
id:"1234",
price:"10,
features:[
{name:"samsung",price:"10"},
{name:"Apple",price:"20"}
]
},
{id:"2154",
price:"20,
features:[
{name:"samsung",price:"30"},
{name:"Moto",price:"40"}
]
]
},
"after":{
"device": [
{
id:"1234",
price:"50,
features:[
{name:"samsung",price:"20"},
{name:"Lenovo",price:"30"}
]
},
{id:"2158",
price:"40,
features:[
{name:"samsung",price:"30"}
]
]
}
}
Expected grouping to be shown in UI is shared in image.
I tried to get unique ids in one array and lopping through after array and comparing unique array id I am getting unique id to show but issue i am facing while grouping their related feature.
Can anyone please help me to get a best approach to handle this requirement.
Thanks
There are 3 things i'd suggest you:
1.) Please verify the data your'e posting is correct and in proper format, people won't be able to help if the data is incorrect.
2.) The UI display requirement should be simple enough.
Now, if you still want to achieve this requirement i believe the correct JSON and the merged output json will look something like below:
//Correct input data that you have:
var input = {
"before": {
"device": [
{
"id": "1234",
"price": "10",
"features": [
{
"name": "samsung",
"price": "10"
},
{
"name": "Apple",
"price": "20"
}
]
},
{
"id": "2154",
"price": "20",
"features": [
{
"name": "samsung",
"price": "30"
},
{
"name": "Moto",
"price": "40"
}
]
}
]
},
"after": {
"device": [
{
"id": "1234",
"price": "50",
"features": [
{
"name": "samsung",
"price": "20"
},
{
"name": "Lenovo",
"price": "30"
}
]
},
{
"id": "2158",
"price": "40",
"features": [
{
"name": "samsung",
"price": "30"
}
]
}
]
}
};
// Output JSON which you should need to show the desired output.
var output = {
"devices": [
{
"id": 1234,
"feature": [
{
"name": "1234",
"price": {
"before": 10,
"after": 50
}
},
{
"name": "samsung",
"price": {
"before": 10,
"after": 20
}
},
{
"name": "apple",
"price": {
"before": 10,
"after": 0
}
},
{
"name": "lenovo",
"price": {
"before": 0,
"after": 30
}
}
]
}
]
};
3.) Please try to get the desired output from input yourself as this will help you learn a lot of things in between, as suggested by some please use map, filter, forEach for your requirement.
Hope this helps. Thanks!
You could take a nested approach for grouping.
var data = { before: { device: [{ id: "1234", price: "10", features: [{ name: "samsung", price: "10" }, { name: "Apple", price: "20" }] }, { id: "2154", price: "20", features: [{ name: "samsung", price: "30" }, { name: "Moto", price: "40" }] }] }, after: { device: [{ id: "1234", price: "50", features: [{ name: "samsung", price: "20" }, { name: "Lenovo", price: "30" }] }, { id: "2158", price: "40", features: [{ name: "samsung", price: "30" }] }] } },
cols = Object.fromEntries(Object.keys(data).map(k => [k, 0])),
result = Object.values(Object.entries(data).reduce((r, [col, { device }]) => {
device.forEach(({ id, price, features }) => {
r[id] = r[id] || [{ id, ...cols }];
r[id][0][col] = price;
features.forEach(({ name, price }) => {
let temp = r[id].find(q => q.name === name);
if (!temp) r[id].push(temp = { name, ...cols });
temp[col] = price;
});
});
return r;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use lodash library for grouping
https://lodash.com/docs/3.10.1#groupBy
Comparing 2 objects, and output equivalent values
var has = {"before":[{
name: 'Nokia',
os: 'Andriod',
features: {
camera: "200 MPixel Camera",
battery: "24 hours battery backup",
}
}],
"after":[{
name: 'Samsung',
os: 'Andriod',
features: {
camera: "200 MPixel Camera",
battery: "30 hours battery backup",
}
}]
};
function compare(Pro1, Pro2) {
var Val1 = Object.values(Pro1);
var Val2 = Object.values(Pro2);
var equivalent = [];
var keys = Object.keys(Pro1);
keys.forEach(k => {
if (Pro1.hasOwnProperty(k) && Pro2.hasOwnProperty(k)) {
if (typeof Pro1[k] === 'object') {
let recursiveResult = compare(Pro1[k], Pro2[k]);
equivalent.push(...recursiveResult);
} else if (Pro1[k] === Pro2[k]) {
equivalent.push(Pro1[k]);
}
}
});
return equivalent;
}
let equiv = compare(has["before"], has["after"]);
console.log(equiv);

How to generate a nested array of objects from an source json object

Using the value from an array of object I'm trying to generate an another array of objects with a different structure than that of the original array.
In the following example arrays you can see that from the key:value pairs the key is changing between the Source array and Result array but the values are same. I had tried some code but not worthwhile to share. What logic or method can be used in this case to generate the object structure mentioned below
Source array
[
{
"node": {
"Charecter": "Hulk",
"Publisher": "Marvel",
"Movie": "Avengers"
}
},
{
"node": {
"Charecter": "Wolverine",
"Publisher": "Marvel",
"Movie": "X-Men"
}
},
{
"node": {
"Charecter": "Superman",
"Publisher": "DC",
"Movie": "Man of steel"
}
}
]
Result array
[
{
"Franchise": "Marvel",
"Data": [
{
"Lead": "Hulk",
"In": "Avengers"
},
{
"Lead": "Wolverine",
"In": "X-Men"
}
]
},
{
"Franchise": "DC",
"Data": [
{
"Lead": "Superman",
"In": "Man of steer"
}
]
},
]
Using .reduce() and .find() combination you can achieve the goal.
Try the following:
const data = [{ "node": { "Charecter": "Hulk", "Publisher": "Marvel", "Movie": "Avengers" } }, { "node": { "Charecter": "Wolverine","Publisher": "Marvel","Movie": "X-Men" } }, {"node": { "Charecter": "Superman", "Publisher": "DC","Movie": "Man of steel" } }];
const result = data.reduce((a, c) => {
const found = a.find(e => e.Franchise === c.node.Publisher);
if (found) found.Data.push({ Lead: c.node.Charecter, In: c.node.Movie });
else a.push({ Franchise: c.node.Publisher, Data: [{ Lead: c.node.Charecter, In: c.node.Movie }] });
return a;
}, []);
console.log(result)
I hope this helps!
You can do it with Array#reduce method where group everything within an object and extract object values using Object.values method.
const data = [{"node":{"Charecter":"Hulk","Publisher":"Marvel","Movie":"Avengers"}},{"node":{"Charecter":"Wolverine","Publisher":"Marvel","Movie":"X-Men"}},{"node":{"Charecter":"Superman","Publisher":"DC","Movie":"Man of steel"}}]"
const result = Object.values(data.reduce((obj, { node: { Publisher: p, ...rest }}) => {
// define key if not defined
obj[p] = obj[p] || { Franchise: p, Data: [] };
// push to the array
obj[p].Data.push(rest);
return obj;
}, {}));
console.log(result)

How to compare two objects with lodash and return new object?

Here are two objects I need to compare and return specific values from object1 if found in object2.
object1 = {
"body": {
"items": [
{
"data": {
"name": "Smith",
"status": "Ready",
"userinfo": [
{
"dob": "01/01/2000",
"nickname": "Joe"
}
]
},
"workinfo": {
"company": "mycompany",
"address": "101 Main str."
}
},
{
"data": {
"name": "Luke",
"status": "Ready",
"userinfo": [
{
"dob": "01/01/2001",
"nickname": "LL"
}
]
},
"workinfo": {
"company": "mycompany",
"address": "101 Main str."
}
}
]
}
}
Object2 is even simple one:
object2 = {
"items": [
{
"name": "Smith",
"status": "Ready"
},
{
"name": "Luke",
"status": "Ready"
}
]
}
So if Object1 body.items[x].data.name found in Object2 items.name then finally I need to get new object like this:
object3 = {{name: "Smith", status: "Ready"}, {name: "Luke", status: "Ready"}}
You can use filter and find:
var obj1 = {
"body": {
"items": [{
"data": {
"name": "Smith",
"status": "Ready",
"userinfo": [{
"dob": "01/01/2000",
"nickname": "Joe"
}]
},
"workinfo": {
"company": "mycompany",
"address": "101 Main str."
}
},
{
"data": {
"name": "Luke",
"status": "Ready",
"userinfo": [{
"dob": "01/01/2001",
"nickname": "LL"
}]
},
"workinfo": {
"company": "mycompany",
"address": "101 Main str."
}
}
]
}
}
var obj2 = {
"items": [{
"name": "Smith",
"status": "Ready"
},
{
"name": "Luke",
"status": "Ready"
}
]
}
var output = obj2.items.filter(({name}) => obj1.body.items.find(({data}) => name === data.name))
console.log(output)
Filter will return all the objects that pass the find condition, that is, if the name is found in obj1
You can use _.intersectionWith() to return items from obj2, that their name equals data.name in obj2 items:
const obj1 = {"body":{"items":[{"data":{"name":"Smith","status":"Ready","userinfo":[{"dob":"01/01/2000","nickname":"Joe"}]},"workinfo":{"company":"mycompany","address":"101 Main str."}},{"data":{"name":"Luke","status":"Ready","userinfo":[{"dob":"01/01/2001","nickname":"LL"}]},"workinfo":{"company":"mycompany","address":"101 Main str."}}]}}
const obj2 = {"items":[{"name":"Smith","status":"Ready"},{"name":"Luke","status":"Ready"}]}
const result = _.intersectionWith(obj2.items, obj1.body.items,
(a, b) => _.get(a, 'name') === _.get(b, 'data.name')
)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
With ES6 this is an easy task with Array.filter and Array.some:
const obj1 = {"body":{"items":[{"data":{"name":"Smith","status":"Ready","userinfo":[{"dob":"01/01/2000","nickname":"Joe"}]},"workinfo":{"company":"mycompany","address":"101 Main str."}},{"data":{"name":"Luke","status":"Ready","userinfo":[{"dob":"01/01/2001","nickname":"LL"}]},"workinfo":{"company":"mycompany","address":"101 Main str."}}]}}
const obj2 = {"items":[{"name":"Smith","status":"Ready"},{"name":"Luke","status":"Ready"}]}
const r = obj2.items.filter(x => obj1.body.items.some(y => y.data.name == x.name))
console.log(r)
Since you have the objects in the correct layout in obj2 you can start from there and filter them against obj1.

Get Object's Parent Without Using Loops in Lodash

Is there a way/function(s) in lodash to get the object's parent of a particular pet id without having to write code that would loop over each person/pet?
For example: _.getParent(people, pets.id => 11) // returns {"type":"Fish", "id":11}.
let people = [
{
"name": "Jack",
"pets": [
{ "type":"Frog", "id":23 },
{ "type":"Bird", "id":57 },
{ "type":"Fish", "id":11 }
]
},
{
"name": "Dawn",
"pets": [
{ "type":"Lion", "id":89 },
{ "type":"Duck", "id":51 }
]
},
{
"name": "Anne"
},
{
"name": "Josh",
"pets": []
}
]
For example,
_.filter(
_.flatMap(people, 'pets'),
t => t && t.id === 11
)

get value of a field from json

I have a JSON that looks like this:
{
"name": "A1",
"aaaaa": [
{
"name": "B1",
"teststr": [
{
"name": "C1",
"state": false,
},
{
"name": "C2",
"state": false,
}
]
},
{
"name": "B2",
"teststr": [
{
"name": "C3",
"state": false,
}
]
}
]
}
I am using JavaScript.
Now, within A1, I have to find a specific "testStr" with name "C1" and change its "state" from false to true. Keys "aaaaa" and "teststr" are unique. And all "teststr"s have unique name.
Can someone please help me with this?
You could go this way:
var smallObject = object.aaaaa.filter(function (o) {
return o.name === "B1";
})[0];
var smallerObject = smallObject.teststr.filter(function (o) {
return o.name === "C1";
})[0];
smallerObject.state = true;
Where object is the literal object that you mentioned in the problem definition.

Categories