How to move nested object into top level without removing top level? - javascript

suppose i have this data:
data = [{
"_id" : "2fApaxgiPx38kpDLA",
"profile" : {
"name" : "Karina 1",
"avatar" : "avatar1.jpg",
"bio" : "my bio 1"
},
{
"_id" : "NXM6H4EWfeRAAhB7c",
"profile" : {
"name" : "Karina 2",
"avatar" : "avatar2.jpg",
"bio" : "my bio 2"
},
}];
i did _.map(data, "profile") but it remove top level _id:
wrongResult = [{
"name" : "Karina 1",
"avatar" : "avatar1.jpg",
"bio" : "my bio 1"
},
{
"name" : "Karina 2",
"avatar" : "avatar2.jpg",
"bio" : "my bio 2"
}];
How to move nested object into top level without removing top level like this one:
expectedResult = [{
"_id" : "2fApaxgiPx38kpDLA",
"name" : "Karina 1",
"avatar" : "avatar1.jpg",
"bio" : "my bio 1"
},
{
"_id" : "NXM6H4EWfeRAAhB7c",
"name" : "Karina 2",
"avatar" : "avatar2.jpg",
"bio" : "my bio 2"
}];
thank You so much....

Something Like this? (not tested)
_.map(data,function(d){
d.profile._id = d._id;
return d.profile;
});

Recently needed to do something like this myself. Ended up writing a general purpose function to bring all (nested included) object values to the top level:
const reduceObjValues = (obj, cache = {}) => {
const objectValues = Object.keys(obj).reduce((acc, cur) => {
if (!Array.isArray(obj[cur]) && typeof obj[cur] === 'object') {
return reduceObjValues({ ...acc, ...obj[cur] }, cache);
}
acc[cur] = obj[cur];
return acc;
}, {});
return {
...objectValues,
...cache,
};
}
reduceObjValues({
a: {
b: 'a',
c: 'b',
},
d: {
e: 'a',
f: {
g: {
h: [
1,
2,
3,
]
}
}
}
});
=> { b: 'a', c: 'b', e: 'a', h: [ 1, 2, 3 ] }
one issue with this function is that it will overwrite any keys that are the same.

You can use flatten to move the nested object to its parent level... https://www.npmjs.com/package/flat

Since you are using lodash, I came up with a generic function to flatten out any deeply nested object.
const flattener = obj => {
const toPairs = obj => _.entries(obj).map(([key, val]) => typeof val === 'object' ? toPairs(val) : [key, val]);
return _.chain(toPairs(obj)).flattenDeep().chunk(2).fromPairs().value();
}
So, with an array like this
data = [
{
"_id" : "2fApaxgiPx38kpDLA",
"profile" : {
"name" : "Karina 1",
"avatar" : "avatar1.jpg",
"bio" : "my bio 1"
}
},
{
"_id" : "NXM6H4EWfeRAAhB7c",
"profile" : {
"name" : "Karina 2",
"avatar" : "avatar2.jpg",
"bio" : "my bio 2"
},
}
]
you can do
data.map(obj => flattener(obj))
which will give you
[
{
"_id": "2fApaxgiPx38kpDLA",
"name": "Karina 1",
"avatar": "avatar1.jpg",
"bio": "my bio 1"
},
{
"_id": "NXM6H4EWfeRAAhB7c",
"name": "Karina 2",
"avatar": "avatar2.jpg",
"bio": "my bio 2"
}
]
NB: This flattener function will throw away duplicate object keys, so if you have an object like;
myObj = { name: 'rick', age: 10, country: { name: 'uganda' } }
Flattening this out by calling flattener(myObj) will result in
{ name: 'uganda', age: 10 }
and not in
{ name: 'uganda', age: 10, name: 'rick' }
because you can't have an object with 2 similar keys even if the values to those keys are unique.

Related

How to transform this specific js array into js object?

I have one javascript array got from back end api, for convenience, need to be sort into the form of below, described as final target.
But I don't know how to start. Anyone can help?
The original src array is like below :
var src = [
{
"parent_kind" : "Animal",
"name" : "Cow"
},
{
"name" : "Animal"
},
{
"parent_kind" : "Animal",
"name" : "Dog"
},
{
"parent_kind" : "Animal",
"name" : "Horse"
},
{
"name" : "Vehicle"
},
{
"parent_kind" : "Vehicle",
"name" : "Bus"
},
{
"parent_kind" : "Bus",
"name" : "Shuttle"
},
]
The final target is :
{
"Vehicle" : {
"Bus" : {
"Shuttle" : {}
}
},
"Animal" : {
"Cow" : {},
"Dog" : {},
"Horse" : {}
}
}
I can got each element of the original array by
for (let ele of src) {
console.log(ele)
}
you can do that with a simple Array.reduce() method
var src =
[ { parent_kind: 'Animal', name: 'Cow' }
, { name: 'Animal' }
, { parent_kind: 'Animal', name: 'Dog' }
, { parent_kind: 'Animal', name: 'Horse' }
, { name: 'Vehicle' }
, { parent_kind: 'Vehicle', name: 'Bus' }
, { parent_kind: 'Bus', name: 'Shuttle' }
]
let res = src.reduce((a,{parent_kind,name},i)=>
{
if(!!parent_kind)
{
let np = a.p.find(x=>x.pN===parent_kind)
if(!np)
{
a.r[parent_kind] = {}
np = {pN:parent_kind, e:a.r[parent_kind]}
a.p.push( np )
}
let z = np.e[name] = {}
a.p.push( {pN:name, e:z} )
}
return (i===a.len)? a.r : a
}
,{len:src.length-1,r:{},p:[]})
console.log( res )
.as-console-wrapper { max-height: 100% !important; top: 0; }
if you can ok with loop the src many times :-( That's performance is not a concern.
var src = [{
"parent_kind": "Animal",
"name": "Cow"
},
{
"name": "Animal"
},
{
"parent_kind": "Animal",
"name": "Dog"
},
{
"parent_kind": "Animal",
"name": "Horse"
},
{
"name": "Vehicle"
},
{
"parent_kind": "Vehicle",
"name": "Bus"
},
{
"parent_kind": "Bus",
"name": "Shuttle"
},
];
const fn = (source, result, parent) => {
const children = source.filter(({
parent_kind
}) => parent_kind === parent).map(({
name
}) => name);
children.forEach(c => result[c] = {});
children.forEach(c => fn(source, result[c], c));
}
result = {};
fn(src, result)
console.log(result);

Getting empty data while trying to get desired format of object

I have an object
"data" : [
{
"name" : "Heading",
"text" : "Text Heading",
"type" : "string",
"values" : [
"Arthur"
]
},
{
"name" : "Source",
"text" : "Source Reference",
"type" : "string",
"values" : [
"Jhon"
]
},
{
"name" : "Place",
"text" : "Bank Building",
"type" : "string",
"values" : [
"Mark"
]
},
{
"name" : "Animal",
"text" : "Branch",
"type" : "string",
"values" : [
"Susan"
]
}
]
there is a function i am passing the object and an array as the arguments
fieldArray=["Heading", "Animal"]
myFunction(fieldArray, data){
... your code here
}
I need to get the output in the below format where I have to search the object with the fields in myArray with the name key of data. Then I need to put the value of the searched object in the below format
[{
"id": 1,
"cells": [{
"id": "ConstId",
"cellContent": "Heading"
},
{
"id": "ConstValue",
"cellContent": "Arthur"
}
]
},
{
"id": 2,
"cells": [{
"id": "ConstId",
"cellContent": "Animal"
},
{
"id": "ConstValue", //a constant field name as ConstValue
"cellContent": "Susan" // the value of the second field in the myArray from object with name Animal
}
]
}
]
I have tried this
const getFormattedData = (fieldArray: any, data: any) => {
let innerData: any = [];
for (let i=0; i<fieldArray.length; i++){
const indexNumber = data.find((key: any) => key.name === fieldArray[i])
if(indexNumber != undefined){
innerData.push({
id: i+1,
cells:[{
id: 'inquiryName',
cellContent: indexNumber.name
},
{
id: 'value',
cellContent: indexNumber.values.toString()
}
]
})
}
console.log('innerData :>> ', innerData);
}
}
You could use the below. Since you tagged javascript, posting answer in JS.
function formatData(data, fieldArray) {
let ret = [];
fieldArray.forEach((field, i) => {
let dataObj = data.filter(d => d.name === field)[0]
if( dataObj ) {
ret.push({
"id": 1,
"cells": [{
"id": "ConstId",
"cellContent": field
},
{
"id": "ConstValue",
"cellContent": dataObj.values[0] //Put whole obj or just first
}
]
})
}
})
return ret;
}
Link to plnkr

Access title inside id

I am having trouble to access title inside an ID object.
I want to access item.title. But i am not able to give a name to the object ID.
I tried doing order.cart.items.item.title
"_id" : ObjectId("5d60d1752cda6403e4f868af"),
"created_at" : ISODate("2019-08-24T05:55:34.741Z"),
"user" : ObjectId("5d60d00e4c865312ccf3f18a"),
"cart" : {
"items" : {
"5d60cddb69f460191c680e96" : {
"item" : {
"_id" : "5d60cddb69f460191c680e96",
"imagePath" : "https://dks.scene7.com/is/image/GolfGalaxy/18NIKWRMX270XXXXXLFS_Black_Cream?wid=1080&fmt=jpg",
"title" : "Nike ",
"description" : "Nike Airmax",
"price" : 10,
"category" : "shoes",
"__v" : 0
},
"qty" : 1,
"price" : 10
}
},
"totalQty" : 1,
"totalPrice" : 10
},
You need to use Object.values for that, because of the ID. This allows you to get the object with the key of 5d60cddb69f460191c680e96 without the key:
Object.values(order.cart.items)[0].item.title
const data = {
"cart" : {
"items" : {
"5d60cddb69f460191c680e96" : {
"item" : {
"_id" : "5d60cddb69f460191c680e96",
"imagePath" : "https://dks.scene7.com/is/image/GolfGalaxy/18NIKWRMX270XXXXXLFS_Black_Cream?wid=1080&fmt=jpg",
"title" : "Nike ",
"description" : "Nike Airmax",
"price" : 10,
"category" : "shoes",
"__v" : 0
},
"qty" : 1,
"price" : 10
}
},
"totalQty" : 1,
"totalPrice" : 10
}};
for (let id in data.cart.items)
console.log(data.cart.items[id].item.title);
You can simply achieve this by getting key name of an object using Object.keys() methods, This methods returns an array of key names
const obj = { id: 1 };
const keysArray = Object.keys(obj);
console.log(keysArray);. // ["id"]
In your case only one keys are present in the object, So we can directly get that name with index 0 (Object.keys(obj)[0])
Check below snippet
const cart ={
"items": {
"5d60cddb69f460191c680e96": {
"item": {
"_id":
"5d60cddb69f460191c680e96",
"imagePath": '',
"title": "Nike ",
"description": "Nike",
"price": 10,
"category": "shoes",
"__v": 0
},
"qty": 1,
"price": 10
}
}
};
const id =
Object.keys(cart.items)[0];
console.log(
cart.items[id].item.title
);

How can i get pair of the json object in javascript

data =
{"user" : [
{
"id" : 1,
"name" : "jeboo",
"level": 1
},
{
"id" : 2,
"name" : "yoyo",
"level": 1
},
{
"id" : 3,
"name" : "yaya",
"level": 2
},
{
"id" : 4,
"name" : "yeye",
"level": 2
},
{
"id" : 5,
"name" : "yiyi",
"level": 3
},
{
"id" : 6,
"name" : "jebee",
"level": 3
}
]}
this is how i get json object
var obj = JSON.stringify(data);
var parse = JSON.parse(obj);
$.each(parse, function(key, object) {
$.each(object, function(index, val) {
console.log(index, val);
});
});
my purpose is want to produce the array below
object 0 + object 1 = first pair
object 2 + object 3 = second pair
object 4 + object 5 = third pair
Assuming you want objects with same level in pairs,
You can use Array#reduce to achieve this:
var data =
{"user" : [
{
"id" : 1,
"name" : "jeboo",
"level": 1
},
{
"id" : 2,
"name" : "yoyo",
"level": 1
},
{
"id" : 3,
"name" : "yaya",
"level": 2
},
{
"id" : 4,
"name" : "yeye",
"level": 2
},
{
"id" : 5,
"name" : "yiyi",
"level": 3
},
{
"id" : 6,
"name" : "jebee",
"level": 3
}
]};
var r = data.user.reduce(function(res, obj) {
res[obj.level - 1] = res[obj.level - 1] || [];
res[obj.level - 1].push(obj);
return res;
}, []);
console.log(r);
EDIT
If you want to pair the objects according to their position in the array and independent of level property then you can use callback's index argument and a bit of math:
var r = data.user.reduce(function(res, obj, idx) {
res[Math.floor(idx/2)] = res[Math.floor(idx/2)] || [];
res[Math.floor(idx/2)].push(obj);
return res;
}, []);

JSON Object array inside array find and replace in javascript

I have one JSON Object like this :
var myObject = [
{
"Name" : "app1",
"id" : "1",
"groups" : [
{ "id" : "test1",
"name" : "test group 1",
"desc" : "this is a test group"
},
{ "id" : "test2",
"name" : "test group 2",
"desc" : "this is another test group"
}
]
},
{
"Name" : "app2",
"id" : "2",
"groups" : [
{ "id" : "test3",
"name" : "test group 4",
"desc" : "this is a test group"
},
{ "id" : "test4",
"name" : "test group 4",
"desc" : "this is another test group"
}
]
},
{
"Name" : "app3",
"id" : "3",
"groups" : [
{ "id" : "test5",
"name" : "test group 5",
"desc" : "this is a test group"
},
{ "id" : "test6",
"name" : "test group 6",
"desc" : "this is another test group"
}
]
}
];
I have new value available of "name" for specific "id".
How can I replace "name" of specific "id" inside any object ?
And how to count total number of groups among all objects ?
for example : replace name to "test grp45" for id = "test1"
Here is fiddle
http://jsfiddle.net/qLTB7/21/
The following function will search through an object and all of its child objects/arrays, and replace the key with the new value. It will apply globally, so it won't stop after the first replacement. Uncomment the commented line to make it that way.
function findAndReplace(object, value, replacevalue) {
for (var x in object) {
if (object.hasOwnProperty(x)) {
if (typeof object[x] == 'object') {
findAndReplace(object[x], value, replacevalue);
}
if (object[x] == value) {
object["name"] = replacevalue;
// break; // uncomment to stop after first replacement
}
}
}
}
Working jsfiddle: http://jsfiddle.net/qLTB7/28/
Try this
function findAndReplace(object,keyvalue, name) {
object.map(function (a) {
if (a.groups[0].id == keyvalue) {
a.groups[0].name = name
}
})
}
findAndReplace(myObject,"test1" ,"test grp45");
Here's a different approach using Array.prototype.some. It assumes that the Name property in the outer objects should be actually be name (note capitalisation).
function updateNameById(obj, id, value) {
Object.keys(obj).some(function(key) {
if (obj[key].id == id) {
obj[key].name = value;
return true; // Stops looping
}
// Recurse over lower objects
else if (obj[key].groups) {
return updateNameById(obj[key].groups, id, value);
}
})
}
The advantage of some is that it stops as soon as the callback returns true.
I think this should work for you:-
var id = 'test1';
var newname = 'test grp45';
var numberOfGruops = 0;
myObject.forEach(function(app){
numberOfGruops += app.groups.length; //Count all groups in this app
app.groups.forEach(function(group){
if(group.id===id)
group.name = newname; // replace the name
});
});
Maybe a more succinct sol'n
function changeName(objArray, objId, newName) {
objArray.forEach(function(obj) {
if (obj.id === objId) obj.Name = newName;
});
}
Personally: if this were me, when creating these objects, I would create a new obj and key them by id.
var myApps = {};
myObject.forEach(function(o) {
myApps[o.id] = o;
});
=>
{
"1": {
"Name": "app1",
"id": "1",
"groups": [
{
"id": "test1",
"name": "test group 1",
"desc": "this is a test group"
},
{
"id": "test2",
"name": "test group 2",
"desc": "this is another test group"
}
]
}
}
And then you could just do:
myApps['someId'].name = 'This is my new Name'
Check it out here:
http://jsfiddle.net/qLTB7/40/
it should be if (object["id"] == value) instead of if (object[x] == value) in 7th line of PitaJ answer, so whole function will look like:
function findAndReplace(object, value, replacevalue) {
for (var x in object) {
if (object.hasOwnProperty(x)) {
if (typeof object[x] == 'object') {
findAndReplace(object[x], value, replacevalue);
}
if (object["id"] == value) {
object["name"] = replacevalue;
// break; // uncomment to stop after first replacement
}
}
}
}
if you leave object[x] - function will replace name also for objects with other keys values set to "test1", for example
{"id": "xxx", "name": "test group 1", "desc": "test1"}

Categories

Resources