Create an array of objects from another array of objects - javascript

I have an object as follows:
{
"id": 1,
"dataLockVersion": 0,
"auditData": {
"createDate": "2018-09-18T11:41:28.362",
"createUser": "XXX",
"updateDate": null,
"updateUser": null
},
"property1": 14021,
"property2": {...},
"property3": "Obj"
}
And I have an array that contains multiple objects in that format.
I want to create a new array of objects from this array, which will contain objects in this format :
{
"property1": 14021,
"property2": {...},
"property3": "Obj"
}
This is what I tried :
var result = [];
for (i = 0; i < arr.length; i++) {
delete arr[i].auditData;
delete arr[i].dataLockVersion;
delete arr[i].domainObjectDescription;
delete arr[i].id;
result.push(arr[i]);
}
Is there a better way to do this ?

use map and object destructure
const result = array
.map(
({ property1, property2, property3 })
=> ({ property1, property2, property3 }));

You can simply use Array.map() and object destructuring for this:
let arr =[{ "id": 1, "dataLockVersion": 0, "auditData": { "createDate": "2018-09-18T11:41:28.362", "createUser": "XXX", "updateDate": null, "updateUser": null }, "property1": 14021, "property2": {"x" :1}, "property3": "Obj" }, { "id": 1, "dataLockVersion": 0, "auditData": { "createDate": "2018-09-18T11:41:28.362", "createUser": "XXX", "updateDate": null, "updateUser": null }, "property1": 14021, "property2": {"x" :12}, "property3": "Obj" }];
let result = arr.map(({property1,property2,property3})=>Object.assign({},{property1,property2,property3}));
console.log(result);

I'd use lodash.pick as a oneliner clean and efficient solution.
Pretty often it turns out that this kind of logic will be needed in other parts of the app.
In your case it would be:
var newArrayWithPickedProperties = array.map(item => {
return _.pick(item, ['property1', 'property2', 'property3']);
})
If you go this way ensure you import only lodash.pick not entire lodash library.

you can try this:
var data = [
{"id": 1,"dataLockVersion": 0,"auditData": {"createDate": "2018-09-18T11:41:28.362","createUser": "XXX","updateDate": null,"updateUser": null},"property1": 14021,"property2": {},"property3": "Obj"},
{"id": 2,"dataLockVersion": 1,"auditData": {"createDate": "2018-09-18T11:41:28.362","createUser": "YYY","updateDate": null,"updateUser": null},"property1": 140221,"property2": {},"property3": "Obj3"}
];
var res = data.map(function(m){return {property1: m.property1, property2: m.property2, property3: m.property3};})
console.log(res);
Or if you like tricks and all values are string or number or object that contains them, you can use this (in very heavy objects is not recommended):
let data = [
{"id": 1,"dataLockVersion": 0,"auditData": {"createDate": "2018-09-18T11:41:28.362","createUser": "XXX","updateDate": null,"updateUser": null},"property1": 14021,"property2": {},"property3": "Obj"},
{"id": 2,"dataLockVersion": 1,"auditData": {"createDate": "2018-09-18T11:41:28.362","createUser": "YYY","updateDate": null,"updateUser": null},"property1": 140221,"property2": {},"property3": "Obj3"}
];
var res=[];
JSON.stringify(data).replace(/"(property1)"\:(.+?),.+?"(property\d+)"\:(.+?)(?=})/gi, function(a){res.push(JSON.parse("{"+a+"}"));});
console.log(res);

If you have n number of property with fixed 1st 3 keys, you can do destructuring assignment.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
let data = [
{"id": 1,"dataLockVersion": 0,"auditData": {"createDate": "2018-09-18T11:41:28.362","createUser": "XXX","updateDate": null,"updateUser": null},"property1": 14021,"property2": {},"property3": "Obj","property4":"yo","property5":"hey"},
{"id": 2,"dataLockVersion": 1,"auditData": {"createDate": "2018-09-18T11:41:28.362","createUser": "YYY","updateDate": null,"updateUser": null},"property1": 140221,"property2": {},"property3": "Obj3"}
];
const arr=data.map(a=>{
let {id,dataLockVersion,auditData,...props}=a
return props;
}
)
console.log(arr);

If data is from a JSON string, the JSON.parse reviver parameter can be used to exclude properties :
var json = '{"id":1,"dataLockVersion":0,"auditData":{"createDate":"2018-09-18T11:41:28.362","createUser":"XXX","updateDate":null,"updateUser":null},"property1":14021,"property2":"{...}","property3":"Obj"}'
var obj = JSON.parse(json, (key, value) => /id|data/i.test(key) ? void 0 : value)
console.log( obj )

Related

Merge and Dedupe Array of Complex Objects with Arrays

I have a pretty complex problem that I can't seem to figure out. I have two array of objects that I would like to merge scores for. It should merge/append certain properties based on the scores. For example between the two arrays there are 4 total gameId's with 3 of them being unique. When merging it should combine the _scores section if it's the same gameId so in this case it would be both EarthNormal merging. But the problem is sometimes the score in _scores can have duplicate scores so the BAR and BASH almost look the exact same but are different it can be appended but FOO score is the exact same on both so I don't want it merged into the scores (if that makes sense).
const arr1 = [{
"gameId": "AirNormal",
"_scores":
[{
"score": 144701,
"playerName": "FOO",
"fullCombo": true,
"timestamp": 1599968866
}]
}, {
"gameId": "EarthNormal",
"_scores":
[{
"score": 177352,
"playerName": "BAR",
"fullCombo": true,
"timestamp": 1599969253
}, {
"score": 164665,
"playerName": "FOO",
"fullCombo": false,
"timestamp": 1599970971
}]
}];
const arr2 = [{
"gameId": "EarthNormal",
"_scores":
[{
"score": 177352,
"playerName": "BASH",
"fullCombo": false,
"timestamp": 1512969017
}, {
"score": 164665,
"playerName": "FOO",
"fullCombo": false,
"timestamp": 1599970971
}]
}, {
"gameId": "FireNormal",
"_scores":
[{
"_score": 124701,
"_playerName": "FOO",
"_fullCombo": true,
"_timestamp": 1591954866
}]
}];
I would want the final merged array to look like:
mergedArray = [{
"gameId": "AirNormal",
"_scores":
[{
"score": 144701,
"playerName": "FOO",
"fullCombo": true,
"timestamp": 1599968866
}]
}, {
"gameId": "EarthNormal",
"_scores":
[{
"score": 177352,
"playerName": "BAR",
"fullCombo": true,
"timestamp": 1599969253
}, {
"score": 177352,
"playerName": "BASH",
"fullCombo": false,
"timestamp": 1512969017
}, {
"score": 164665,
"playerName": "FOO",
"fullCombo": false,
"timestamp": 1599970971
}]
}, {
"gameId": "FireNormal",
"_scores":
[{
"score": 124701,
"playerName": "FOO",
"fullCombo": true,
"timestamp": 1591954866
}]
}]
I have tried doing this and using lodash:
let merged = [...arr1, ...arr2];
merged = _.uniqBy[merged, 'gameId']
let scoresMerge = _.uniqBy[merged, '_scores']
console.log(scoresMerge);
but it didn't work as I expected. Am I approaching this incorrectly?
This is fairly straight forward using vanilla javascript.
merge the arrays using destructuring
reduce() the merged arrays into an object indexed by gameId
check all properties of each _score object against the accumulated _scores array using .some() and push if no match is found.
return the values of the reduced object using Object.values()
const arr1 = [{ "gameId": "AirNormal", "_scores": [{ "score": 144701, "playerName": "FOO", "fullCombo": true, "timestamp": 1599968866 }]}, { "gameId": "EarthNormal", "_scores": [{ "score": 177352, "playerName": "BAR", "fullCombo": true, "timestamp": 1599969253 }, { "score": 164665, "playerName": "FOO", "fullCombo": false, "timestamp": 1599970971 }]}];
const arr2 = [{"gameId": "EarthNormal","_scores":[{"score": 177352,"playerName": "BASH","fullCombo": false,"timestamp": 1512969017}, {"score": 164665,"playerName": "FOO","fullCombo": false,"timestamp": 1599970971}]}, {"gameId": "FireNormal","_scores":[{"_score": 124701,"_playerName": "FOO","_fullCombo": true,"_timestamp": 1591954866}]}];
const merged = Object.values([...arr1, ...arr2].reduce((a, {gameId, _scores}) => {
// retrieve gameId object otherwise initialize it.
a[gameId] = {...a[gameId] ?? {gameId, _scores: []}};
// iterate over all _score objects
_scores.forEach(s => {
// if accumulator _scores array doesn't have an object matching all properties, push _score
if (!a[gameId]['_scores'].some(o => {
return !Object.entries(s).some(([k, v]) => o[k] !== v)})
) {
a[gameId]['_scores'].push({...s});
}
});
return a;
}, {}));
console.log(merged);
You need to identify objects with the same gameId, and then concat and dedupe their _.scores array.
It's easy to concat/dedup non primitive array items using Array.reduce() and a Map. For every item you check if the requested key is already in the Map. If it's not, you assign the current item to the Map's key. If it is you replace / merge the current item with the item in the Map.
After you finish iterating the Map, use Array.from() to convert the Map's .values() iterator to an array.
const arr1 = [{"gameId":"AirNormal","_scores":[{"score":144701,"playerName":"FOO","fullCombo":true,"timestamp":1599968866}]},{"gameId":"EarthNormal","_scores":[{"score":177352,"playerName":"BAR","fullCombo":true,"timestamp":1599969253},{"score":164665,"playerName":"FOO","fullCombo":false,"timestamp":1599970971}]}];
const arr2 = [{"gameId":"EarthNormal","_scores":[{"score":177352,"playerName":"BASH","fullCombo":false,"timestamp":1512969017},{"score":164665,"playerName":"FOO","fullCombo":false,"timestamp":1599970971}]},{"gameId":"FireNormal","_scores":[{"score":124701,"playerName":"FOO","fullCombo":true,"timestamp":1591954866}]}];
const dedupLastBy = (a1 = [], a2 = [], key) => Array.from(
[...a1, ...a2].reduce((acc, obj) => {
const keyName = obj[key];
if(acc.has(keyName)) acc.delete(keyName);
return acc.set(keyName, obj);
}, new Map()).values()
)
const handleDups = ({ _scores: a, ...o1 }, { _scores: b, ...o2 }) => ({
...o1,
...o2,
_scores: dedupLastBy(a, b, 'playerName')
});
const result = Array.from([...arr1, ...arr2]
.reduce((acc, o) => {
const { gameId } = o;
if(acc.has(gameId)) acc.set(gameId, handleDups(acc.get(gameId), o));
else acc.set(gameId, o);
return acc;
}, new Map()).values());
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>

Unable to convert a nested object into an array of objects and viceversa

I am having an object of the following kind:
var sourceObj = {
"feature1": [
{"id":"1","name":"abc","enabled":false,"type":"type1"},
{"id":"2","name":"xyz","enabled":false,"type":"type1"}
]
,
"feature2": [
{"id":"3","name":"lmn","enabled":true,"type":"type2"},
{"id":"4","name":"pqr","enabled":false,"type":"type2"}
]
}
Need to get converted to an array of objects of the following type:
var destArr = [
{ "feature_name":"feature1",
"feature_details":[
{"id":"1","name":"abc","enabled":false,"type":"type1"},
{"id":"2","name":"xyz","enabled":true,"type":"type1"}
]
},
{ "feature_name":"feature2",
"feature_details":[
{"id":"3","name":"lmn","enabled":true,"type":"type2"}
{"id":"4","name":"pqr","enabled":false,"type":"type2"}
]
}
]
I have tried the following approaches for conversion of source object to resultant array of objects and resultant array of objects back to the source object
//Converting source object to array of objects
let arr = Object.keys(sourceObj).map(key => {
return sourceObj[key];
})
converting array of objects back to source objetc
let obj = Object.assign({}, ...destArr.map(item => ({ [item.name]: item.value })));
You could use Object.entries to map everything in a single shot.
To go back to the original structure, you could use reduce against the generated array (see backToOriginalArray below)
var sourceObj = {
"feature1": [{
"id": "1",
"name": "abc",
"enabled": false,
"type": "type1"
},
{
"id": "2",
"name": "xyz",
"enabled": false,
"type": "type1"
}
],
"feature2": [{
"id": "3",
"name": "lmn",
"enabled": true,
"type": "type2"
},
{
"id": "4",
"name": "pqr",
"enabled": false,
"type": "type2"
}
]
};
// Step 1: use object.entries against the original object to build an array of objects.
var destArray = Object.entries(sourceObj).map(([key, value]) => ({
"feature_name": key,
"feature_details": value
}));
console.log(destArray);
// Step 2: use reduce against the generated array to get an object with the same structure of the original one.
var backToOriginalArray = destArray.reduce((acc, {feature_name, feature_details}) => (acc[feature_name] = feature_details, acc), {});
console.log(backToOriginalArray);
Map the Object.entries of your initial object:
var sourceObj = {
"feature1": [
{"id":"1","name":"abc","enabled":false,"type":"type1"},
{"id":"2","name":"xyz","enabled":false,"type":"type1"}
],
"feature2": [
{"id":"3","name":"lmn","enabled":true,"type":"type2"},
{"id":"4","name":"pqr","enabled":false,"type":"type2"}
]
};
const destArr = Object.entries(sourceObj).map(
([feature_name, feature_details]) => ({ feature_name, feature_details })
);
console.log(destArr);
To go the other way around, use Object.fromEntries:
const arr=[{feature_name:"feature1",feature_details:[{id:"1",name:"abc",enabled:!1,type:"type1"},{id:"2",name:"xyz",enabled:!1,type:"type1"}]},{feature_name:"feature2",feature_details:[{id:"3",name:"lmn",enabled:!0,type:"type2"},{id:"4",name:"pqr",enabled:!1,type:"type2"}]}];
const obj = Object.fromEntries(arr.map(
({ feature_name, feature_details }) => [feature_name, feature_details]
));
console.log(obj);

Convert an array of objects to a hash based on a property of the object

Convert a JSON Array into a map based on key of the JSON object in the array
I'm trying to convert a JSON array into a map based on the property of the JSON element in the array.
Here is the structure of the JSON array:
[
{"property1": "x","property2": "value1","property3": "value1"},
{"property1": "x","property2": "value2","property3": "value2"},
{"property1": "y","property2": "value3","property3": "value3"},
{"property1": "y","property2": "value4","property3": "value4"}
]
I want to split the JSON array into a map like this:
{
"x": [{"property2": "value1","property3": "value1"},
{"property2": "value2","property3": "value2"}],
"y": [{"property2": "value3","property3": "value3"},
{"property2": "value4","property3": "value4"}]
}
How can I do this with Javascript?
(P.S: I'm completely new to Javascript)
JavaScript has Map for maps, so you could do this:
const data = [{"property1": "x","property2": "value1","property3": "value1"},{"property1": "x","property2": "value2","property3": "value2"},{"property1": "y","property2": "value3","property3": "value3"},{"property1": "y","property2": "value4","property3": "value4"}];
const map = new Map(data.map(o => [o.property1, []]));
data.forEach(({property1, ...rest}) => map.get(property1).push(rest));
const result = Object.fromEntries(map);
console.log(result);
The last assignment converts the Map to a plain object in case you don't like working with Maps.
ES5
Map, arrow functions, object literal spread syntax, ...etc are not available in ES5. In that version of JavaScript you would do this:
const data = [{"property1": "x","property2": "value1","property3": "value1"},{"property1": "x","property2": "value2","property3": "value2"},{"property1": "y","property2": "value3","property3": "value3"},{"property1": "y","property2": "value4","property3": "value4"}];
var map = {}
data.forEach(function (o) {
var cpy = Object.assign({}, o);
delete cpy.property1;
map[o.property1] = (map[o.property1] || []).concat(cpy);
});
console.log(map);
Try the code below:
let a = [{
"property1": "x",
"property2": "value1",
"property3": "value1"
},
{
"property1": "x",
"property2": "value2",
"property3": "value2"
},
{
"property1": "y",
"property2": "value3",
"property3": "value3"
},
{
"property1": "y",
"property2": "value4",
"property3": "value4"
}
];
let b = {};
for (o of a) {
b[o.property1] = b[o.property1] || [];
b[o.property1].push({
property2: o.property2,
property3: o.property3
});
}
console.log(b);
What this code does is first creates a an array property for each property1 if it doesn't already exist. Then it pushes a new object in that array with only the property2 and property3.
For a functional approach you can use Object.values:
var o = [
{"property1": "x","property2": "value1","property3": "value1"},
{"property1": "x","property2": "value2","property3": "value2"},
{"property1": "y","property2": "value3","property3": "value3"},
{"property1": "y","property2": "value4","property3": "value4"}
]
var r = Object.values(o).reduce((ac, x) => ({
...ac,
[x.property1]: [
...(ac[x.property1] || []),
x
]
}), {})
console.log(r)
You can get this via Array.reduce and then decide if you want to start with an object literal or a Map:
With Map:
let data = [{ "property1": "x", "property2": "value1", "property3": "value1" }, { "property1": "x", "property2": "value2", "property3": "value2" }, { "property1": "y", "property2": "value3", "property3": "value3" }, { "property1": "y", "property2": "value4", "property3": "value4" } ]
let result = data.reduce((r,{property1, property2, property3}) =>
r.set(property1, { property2, property3 }), new Map())
console.log(Object.fromEntries(result))
With object literal as the accumulator:
let data = [{ "property1": "x", "property2": "value1", "property3": "value1" }, { "property1": "x", "property2": "value2", "property3": "value2" }, { "property1": "y", "property2": "value3", "property3": "value3" }, { "property1": "y", "property2": "value4", "property3": "value4" } ]
let result = data.reduce((r,{property1, property2, property3}) => {
r[property1] = r[property1] || []
r[property1].push({ property2, property3 })
return r
}, {})
console.log(result)
Here's my approach to solving this. I'm by no means an expert and I'm sure other users could provide a better solution. But until then you can see if this helps.
Essentially we want to filter out the two collections (x and y) using the .filter expression. Then for those collections, we'll remove the property we used to filter on. Then finally create a new object combining the remaining collections.
JSFiddle: https://jsfiddle.net/u9bxg8wv/1/
const dataSource = [
{"property1": "x","property2": "value1","property3": "value1"},
{"property1": "x","property2": "value2","property3": "value2"},
{"property1": "y","property2": "value3","property3": "value3"},
{"property1": "y","property2": "value4","property3": "value4"}
];
let xContainer = dataSource.filter(x => x.property1 === "x");
let yContainer = dataSource.filter(y => y.property1 === "y");
xContainer.forEach((e) => {
delete e.property1;
});
yContainer.forEach((e) => {
delete e.property1;
});
let mappedDataSource = {
"x": xContainer,
"y": yContainer
};
console.log(mappedDataSource);

How to parse json key dot literals

I have this JSON object, it's a dynamically generated object, I can't control how it's formatted to json. The problem is that the json looks like this:
{
"id": "def",
"name": "def",
"description": {},
"description.shortened": "def",
"description.extended": "def",
"type": "EDIBLE_BOUQUET",
"image": {},
"image.name": "def",
"image.slug": "def",
"image.extension": "PNG",
"state": "FEATURED",
"stock": "def"
}
How would I go about transforming it into:
{
"id": "def",
"name": "def",
"description": {
"shortened": "def",
"extended": "def"
},
"type": "EDIBLE_BOUQUET",
"image": {
"name": "def",
"slug": "def",
"extension": "PNG"
},
"state": "FEATURED",
"stock": "def"
}
let obj = {
"id": "def",
"name": "def",
"description": {},
"description.shortened": "def",
"description.extended": "def",
"type": "EDIBLE_BOUQUET",
"image": {},
"image.name": "def",
"image.slug": "def",
"image.extension": "PNG",
"state": "FEATURED",
"stock": "def"
}
const transformObj = obj => {
return Object.keys(obj).reduce((acc, key) => {
if(key.indexOf('.') >= 0){
const [parentKey, childKey] = key.split('.');
acc[parentKey] = acc[parentKey] || {};
acc[parentKey][childKey] = obj[key];
} else {
acc[key] = obj[key];
}
return acc;
}, {});
}
console.log(transformObj(obj));
Iterate through the keys of object, and transform it.
function transform(obj){
let tmp={}
Object.keys(obj).forEach(k=>{
if(k.includes('.')){
let path=k.split('.')
let x=path.pop()
path.reduce((cur,p)=>{
if(!(p in cur))cur[p]={}
return cur[p]
},tmp)[x]=obj[k]
}
else{
tmp[k]=obj[k]
}
})
return tmp
}
const obj={
a: 1,
'b.c.d': 2
}
console.log(transform(obj)) // {a: 1, b: {c: {d: 2}}}
If you're in for using lodash, _.set does exactly what you're trying to do here:
const source = {"id":"def","name":"def","description":{},"description.shortened":"def","description.extended":"def","type":"EDIBLE_BOUQUET","image":{},"image.name":"def","image.slug":"def","image.extension":"PNG","state":"FEATURED","stock":"def"};
let target = {};
Object.keys(source).forEach(key => {
_.set(target, key, source[key]);
});
console.log(target);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
Just one catch, the parent property should always be before the child properties in your source object, i.e. description should occur before description.shortened.
Fairly straight forward.
Check each property to see if the name contains a ., add the correct property and delete the original.
const src = {
"id": "def",
"name": "def",
"description": {},
"description.shortened": "def",
"description.extended": "def",
"type": "EDIBLE_BOUQUET",
"image": {},
"image.name": "def",
"image.slug": "def",
"image.extension": "PNG",
"state": "FEATURED",
"stock": "def"
};
for (var k in src) {
let index = k.indexOf('.');
if (index > 0){
let [base, prop] = k.split('.');
let value = src[k];
delete src[k]
src[base][prop] = value;
}
}
console.log(src)
Using lodash's set method would be the easiest path.
const json = '{"id": "def","name": "def","description": {},"description.shortened": "def","description.extended": "def","type": "EDIBLE_BOUQUET","image": {},"image.name": "def","image.slug": "def","image.extension": "PNG","state": "FEATURED","stock": "def"}';
const obj = JSON.parse(json);
const newObj = Object.keys(obj).reduce((o, k) => _.set(o, k, obj[k]), {});
console.log(newObj);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.5/lodash.min.js"></script>
A concern should be noted that if the object keys are not guaranteed to be in the order shown, some data may be lost. See the following example.
const json = '{"id": "def","name": "def","description.shortened": "def","description.extended": "def","description": {},"type": "EDIBLE_BOUQUET","image": {},"image.name": "def","image.slug": "def","image.extension": "PNG","state": "FEATURED","stock": "def"}';
const obj = JSON.parse(json);
const newObj = Object.keys(obj).reduce((o, k) => _.set(o, k, obj[k]), {});
console.log(newObj);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.5/lodash.min.js"></script>
Since the set method iterates over the keys in the order provided from the keys method, the last key will set the value to whatever is provided. So, if the description: {} pair follows any previous description.x: y pair then those values will be lost once the empty object is assigned.
A simple fix would be to include a sort to force the empty object pair to be the first key provided. Note however this will also cause the rest of the object to no longer be in the same order as the original.
const json = '{"id": "def","name": "def","description.shortened": "def","description.extended": "def","description": {},"type": "EDIBLE_BOUQUET","image": {},"image.name": "def","image.slug": "def","image.extension": "PNG","state": "FEATURED","stock": "def"}';
const obj = JSON.parse(json);
const newObj = Object.keys(obj).sort().reduce((o, k) => _.set(o, k, obj[k]), {});
console.log(newObj);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.5/lodash.min.js"></script>
If you do need to roll your own then something like the following would suffice:
const json = '{"id": "def","name": "def","description.shortened": "def","description.extended": "def","description": {},"type": "EDIBLE_BOUQUET","image": {},"image.name": "def","image.slug": "def","image.extension": "PNG","state": "FEATURED","stock": "def"}';
const obj = JSON.parse(json);
const newObj = Object.keys(obj).sort().reduce((o, k) => {
const paths = k.split('.');
// Get to currently defined depth of object
let depth = 0;
let oRef = o;
while (oRef.hasOwnProperty(paths[depth])) {
oRef = oRef[paths[depth++]];
}
const val = paths.slice(depth).reduceRight((v, p) => ({[p]: v}), obj[k]);
Object.assign(oRef, val);
return o;
}, {});
console.log(newObj);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.5/lodash.min.js"></script>

Restructure JSON object

I have the following array:
var res = {
"status": "Success",
"data": [
{"assignedTo":"0", "createdDate":"23-07-2013", "count":"2"},
{"assignedTo":"182398", "createdDate":"01-08-2013", "count":"2"},
{"assignedTo":"182398", "createdDate":"23-07-2013", "count":"2"},
{"assignedTo":"182398", "createdDate":"24-07-2013", "count":"12"},
{"assignedTo":"182398", "createdDate":"22-07-2013", "count":"1"},
{"assignedTo":"182398", "createdDate":"30-07-2013", "count":"4"},
{"assignedTo":"182398", "createdDate":"31-07-2013", "count":"19"},
{"assignedTo":"185271", "createdDate":"24-07-2013", "count":"2"},
{"assignedTo":"185271", "createdDate":"23-07-2013", "count":"1"}
]
}
Now I want to make one json array from the above with the value of data to another json
which will be like:
[
{
key: "0",
values: [["23-07-2013", 2]]
},
{
key: "182398",
values: [["01-08-2013", 2],
["23-07-2013", 2],
["24-07-2013", 12],
["22-07-2013", 1],
["30-7-2013", 4],
["31-7-2013", 19]
},
{
key: "185271",
values: [["24-07-2013", 2],
["23-07-2013", 1]
}
]
I have tried like the following:
for (i in res.data) {
for (k in res.data[i]) {
time_val += "[" + res.data[i]['createdDate'] + ","
+ res.data[i]['count'] + "],";
cumulative_val += '{key:"' + res.data[i]['assignedTo']
+ '",values:'+time_val+'},';
}
}
Could you please guide me how to do this?
Thanks in advance.
Something like this in javascript:
var res = {"status":"Success","data":[{"assignedTo":"0","createdDate":"23-07-2013","count":"2"},
{"assignedTo":"182398","createdDate":"01-08-2013","count":"2"},
{"assignedTo":"182398","createdDate":"23-07-2013","count":"2"},
{"assignedTo":"182398","createdDate":"24-07-2013","count":"12"},
{"assignedTo":"182398","createdDate":"22-07-2013","count":"1"},
{"assignedTo":"182398","createdDate":"30-07-2013","count":"4"},
{"assignedTo":"182398","createdDate":"31-07-2013","count":"19"},
{"assignedTo":"185271","createdDate":"24-07-2013","count":"2"},
{"assignedTo":"185271","createdDate":"23-07-2013","count":"1"}]
}
//Wanted mixed object
var temp = [];
//Store keys, so we do not need to check from temp if key allready exists
var temp_keys = {};
//Loop trough data
for (var i in res.data)
{
//Check if key is allready stored in object
if (!temp_keys[res.data[i]['assignedTo']])
{
//Store new key, and save it''s position
temp_keys[res.data[i]['assignedTo']] = temp.length;
//Create new array element as new object
temp.push(
{
'key' : res.data[i]['assignedTo'],
'values': []
}
);
}
//Save values into correct position
temp[temp_keys[res.data[i]['assignedTo']]]['values'].push([res.data[i]['createdDate'], res.data[i]['count']]);
}
console.log(temp);
console.log(JSON.stringify(temp));
JSON Example Output:
[{"key":"0","values":[["23-07-2013","2"]]},{"key":"182398","values":[["01-08-2013","2"],["23-07-2013","2"],["24-07-2013","12"],["22-07-2013","1"],["30-07-2013","4"],["31-07-2013","19"]]},{"key":"185271","values":[["24-07-2013","2"],["23-07-2013","1"]]}]
use these functions
json_decode
get_object_vars
I guess that the cumulative_key is in the wrong loop:
lastKey = res.data[0]['assignedTo'];
for(i in res.data) {
if(res.data[i]['assignedTo'] != last) {
cumulative_val += '{key:"'+res.data[i]['assignedTo']+'",values:'+time_val+'},';
}
time_val += "["+res.data[i]['createdDate']+","+res.data[i]['count']+"],";
}
You should think about manipulate real array object and then after make a json encoding.
Try this code...
var _root = new Array();
for (i in res.data) {
for (k in res.data[i]) {
var _child = [res.data[i]['createdDate'], res.data[i]['count']];
var _parent = [{"key":res.data[i]['assignedTo'], "values": _child}];
}
_root.push(_parent);
}
var _JSON_ = JSON.stringify(_root);
A slightly different solution just for the sake of variety
let res = {
"status": "Success", "data": [
{"assignedTo": "185271", "createdDate": "23-07-2013", "count": "1"},
{"assignedTo": "182398", "createdDate": "01-08-2013", "count": "2"},
{"assignedTo": "182398", "createdDate": "23-07-2013", "count": "2"},
{"assignedTo": "182398", "createdDate": "24-07-2013", "count": "12"},
{"assignedTo": "185271", "createdDate": "24-07-2013", "count": "2"},
{"assignedTo": "182398", "createdDate": "22-07-2013", "count": "1"},
{"assignedTo": "0", "createdDate": "23-07-2013", "count": "2"},
{"assignedTo": "182398", "createdDate": "30-07-2013", "count": "4"},
{"assignedTo": "182398", "createdDate": "31-07-2013", "count": "19"},
]
};
let values = [];
let ctrl = '';
let interim = {};
for (const obj of res.data) {
const id = obj.assignedTo;
values = interim[obj.assignedTo] ? interim[obj.assignedTo].values : [];
values.push([obj.createdDate, obj.count])
interim[obj.assignedTo] = {"key": obj.assignedTo, "values": values};
ctrl = ctrl !== id ? id : ctrl;
}
let reshaped = Object.values(interim);
console.log(JSON.stringify(reshaped, null, 0));
and the result is
[{"key": "0", "values": [["23-07-2013", "2"]]},
{"key": "182398", "values": [["01-08-2013", "2"],
["23-07-2013", "2"],
["24-07-2013", "12"],
["22-07-2013", "1"],
["30-07-2013", "4"],
["31-07-2013", "19"]]},
{"key": "185271", "values": [["23-07-2013", "1"],
["24-07-2013", "2"]]}
]
I "shuffled" the input data a bit just to avoid a mistake of assuming the data is always sorted... which I almost fell into twice while was writing up this snippet.

Categories

Resources