I have a nested JSON object which is of the format
[{
firstLevelKey1 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey2:[{
dataType : 'Object'
},{
value : [{
secondLevelKey1 :[{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
secondLevelKey2 : [{
dataType : 'Object'
},{
value : [{
thirdLevelKey1:[{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
thirdLevelKey2 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
thirdLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
}]
},{
someKey : 'someValue'
}]
},{
secondLevelKey3 :[{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
}]
},{
someKey : 'someValue'
}]
},{
firstLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
}]
for easier understanding this is an array of objects, in each object, the value of key is again an array of 3 objects, of which first tells the dataType and there is value in the second object, and some other keys in third object.
If the dataType is Object then the second object which has the key property called value will have again array of objects repeating the procedure.
I am able to flatten and the flattened object is like
[{
firstLevelKey1 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
secondLevelKey1 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
thirdLevelKey1 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
thirdLevelKey2 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
thirdLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
secondLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
}]
but now firstLevelKey2 property name and secondLevelKey2 name are lost
is there a way to store the names so that while mapping back i can know how to nest them back in the same format how i recieved it ?
like for example in this format
[{
firstLevelKey1 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey2#secondLevelKey1 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey2#secondLevelKey2#thirdLevelKey1 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey2#secondLevelKey2#thirdLevelKey2 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey2#secondLevelKey2#thirdLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey2#secondLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
}]
any help would be very appreciated.Thanks!
You could use a recursive approach here, creating a flattenWithPath function that takes an array and path as arguments.
By passing the path for each call we can ensure we can retain the object hierarchy in the key names.
const input = [{ firstLevelKey1 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ firstLevelKey2:[{ dataType : 'Object' },{ value : [{ secondLevelKey1 :[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ secondLevelKey2 : [{ dataType : 'Object' },{ value : [{ thirdLevelKey1:[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ thirdLevelKey2 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ thirdLevelKey3 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] }] },{ someKey : 'someValue' }] },{ secondLevelKey3 :[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] }] },{ someKey : 'someValue' }] },{ firstLevelKey3 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] }]
function flattenWithPath(arr, path = []) {
let result = [];
for (let obj of arr) {
const [key, value] = Object.entries(obj)[0];
if (Array.isArray(value[1].value)) {
result.push(...flattenWithPath(value[1].value, [...path, key]));
} else {
result.push({ [[...path, key].join('#')]: value });
}
}
return result;
}
console.log(JSON.stringify(flattenWithPath(input), null, 2))
.as-console-wrapper { max-height: 100% !important; }
Here's another take.
const input = [{ firstLevelKey1 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ firstLevelKey2:[{ dataType : 'Object' },{ value : [{ secondLevelKey1 :[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ secondLevelKey2 : [{ dataType : 'Object' },{ value : [{ thirdLevelKey1:[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ thirdLevelKey2 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ thirdLevelKey3 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] }] },{ someKey : 'someValue' }] },{ secondLevelKey3 :[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] }] },{ someKey : 'someValue' }] },{ firstLevelKey3 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] }]
function flatObj(obj, path = []) {
return Object.entries(obj).flatMap(([k, v]) =>
v[0].dataType === 'Object' ?
v[1].value.flatMap(obj => flatObj(obj, [...path, k])) :
[{[[...path, k].join('#')]: v}]
);
}
console.log(input.flatMap(obj => flatObj(obj)));
Related
Hello again great minds of stack overflow!
Iam working in an angular project and my question is about mapping JSON objects.
So i have JSON Object that i am taking out from html
it is of the format
const obj = {
firstLevelKey1 : "Value1",
thirdLevelKey2 : [{
"diffKey1": "diffValue1",
"diffKey2" : "diffValue2",
"diffKey3" : "diffValue3"
},{
"diffKey1": "diffValue1",
"diffKey2" : "diffValue2",
"diffKey3" : "diffValue3"
},{
"diffKey1": "diffValue1",
"diffKey2" : "diffValue2",
"diffKey3" : "diffValue3"
}],
thirdLevelKey3 : ["string1", "string2", "string3"]
}
the format I want to map with is like this
const objToMap = [{
firstLevelKey1 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey2:[{
dataType : 'Object'
},{
value : [{
secondLevelKey1 :[{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
secondLevelKey2 : [{
dataType : 'Object'
},{
value : [{
thirdLevelKey1:[{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
thirdLevelKey2 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
thirdLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
}]
},{
someKey : 'someValue'
}]
},{
secondLevelKey3 :[{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
}]
},{
someKey : 'someValue'
}]
},{
firstLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
}]
after getting the flattening with keyNames function from here, the great stack overflow
the json object I can also generate (using innertext property)
const anotherObj = {
"firstLevelKey1" : "firstLevelValue",
"firstLevelKey2#secondLevlKey1" : "secondLevelValue1",
"firstLevelKey2#secondLevelKey2#thirdLevelKey1" : "thirdLevelValue1",
"firstLevelKey2#secondLevelKey2#thirdLevelKey2" : [{
"diffKey1": "diffValue1",
"diffKey2" : "diffValue2",
"diffKey3" : "diffValue3"
},{
"diffKey1": "diffValue1",
"diffKey2" : "diffValue2",
"diffKey3" : "diffValue3"
},{
"diffKey1": "diffValue1",
"diffKey2" : "diffValue2",
"diffKey3" : "diffValue3"
}],
"firstLevelKey2#secondLevelKey2#thirdLevelKey3": ["string1", "string2", "string3"],
"firstLevelKey2#secondLevelKey3" : "secondLevelValue3",
"firstLevelKey3" : "firstLevelValue3"
}
so can I please know how do I map obj/anotherObj to objToMap,
the values from obj/anotherObj should map for value key in objToMap, that is I should send it back in the same format I got in with values added in
any help is greatly appreciated.
I'm pretty new to coding and I'm working on a problem. I can't fully understand how reduce function work.
So basically I have an array of objects which are topics, each topic contains an article. When I click on a button it will append a topic.
I need to append the articles only when I click otherwise it will show all topics without articles.
let buttonValue = 1;
const topics = [{
id: 1,
article: {"date" : "01-01-2022", "title" : "title1", "summary" : "summary1"}
},
{
id: 2,
article: {"date" : "01-01-2022", "title" : "title2", "summary" : "summary2"}
},
{
id: 3,
article: {"date" : "01-01-2022", "title" : "title3", "summary" : "summary3"}
},
{
id: 4,
article: {"date" : "01-01-2022", "title" : "title4", "summary" : "summary4"}
},{
id: 1,
article: {"date" : "01-02-2022", "title" : "title5", "summary" : "summary5"}
},
{
id: 2,
article: {"date" : "01-02-2022", "title" : "title6", "summary" : "summary6"}
},
{
id: 3,
article: {"date" : "01-02-2022", "title" : "title7", "summary" : "summary7"}
},
{
id: 1,
article: {"date" : "01-02-2022", "title" : "title5", "summary" : "summary5"}
},
];
Result should be:
const topics = [
{
id: 1,
article: [{"date" : "01-01-2022", "title" : "title1", "summary" : "summary1"}, {"date" : "01-02-2022", "title" : "title5", "summary" : "summary5"}, {"date" : "01-02-2022", "title" : "title5", "summary" : "summary5"}]
},
{
id: 4,
article: {"date" : "01-01-2022", "title" : "title4", "summary" : "summary4"}
},
{
id: 2,
article: {"date" : "01-02-2022", "title" : "title6", "summary" : "summary6"}
},
{
id: 3,
article: {"date" : "01-02-2022", "title" : "title7", "summary" : "summary7"}
},
];
Here is my code:
const articleArray = topics.reduce((acc,cur) => {
const found = acc.find(topic => topic.id == cur.id && topic.id === buttonValue);
return found ? found.article.push(cur.article) : acc.push({...cur, article:[cur.article]}), acc;
}, []);
const uniqueTopic = Array.from(new Set(articleArray.map(topic => topic.id)))
.map(id => {
return articleArray.find(element => element.id === id)
})
I have some difficulties to understand how the reduce work because when I console log found it returned undefined. Can someone explain it?
Is there another way to directly accumulate and reduce the array without uniqueTopic function?
I tried:
const reducedArr = topics.reduce((acc, cur) => {
acc[cur.id] && (cur.id === buttonValue)
? (acc[cur.id].push({...cur, article:[cur.article]}))
: (acc[cur.id] = cur);
return acc;
}, {});
It returned undefined.
One issue I noticed was no empty array had been initialized to push new items.
Try this to build the reduced array using Object.entries, Array.prototype.reduce, and Array.prototype.map.
const topics = [ { id: 1, article: { date: "01-01-2022", title: "title1", summary: "summary1" }, }, { id: 2, article: { date: "01-01-2022", title: "title2", summary: "summary2" }, }, { id: 3, article: { date: "01-01-2022", title: "title3", summary: "summary3" }, }, { id: 4, article: { date: "01-01-2022", title: "title4", summary: "summary4" }, }, { id: 1, article: { date: "01-02-2022", title: "title5", summary: "summary5" }, }, { id: 2, article: { date: "01-02-2022", title: "title6", summary: "summary6" }, }, { id: 3, article: { date: "01-02-2022", title: "title7", summary: "summary7" }, }, { id: 1, article: { date: "01-02-2022", title: "title5", summary: "summary5" }, }, ];
const reducedArr = Object.entries(
topics.reduce((acc, cur) => {
if (!acc[cur.id]) {
acc[cur.id] = [];
}
acc[cur.id].push(cur.article);
return acc;
}, {})
).map(([id, articles]) => ({ id, articles }));
console.log(reducedArr);
can you check this once please
const topics = [{
id: 1,
article: {"date" : "01-01-2022", "title" : "title1", "summary" : "summary1"}
},
{
id: 2,
article: {"date" : "01-01-2022", "title" : "title2", "summary" : "summary2"}
},
{
id: 3,
article: {"date" : "01-01-2022", "title" : "title3", "summary" : "summary3"}
},
{
id: 4,
article: {"date" : "01-01-2022", "title" : "title4", "summary" : "summary4"}
},{
id: 1,
article: {"date" : "01-02-2022", "title" : "title5", "summary" : "summary5"}
},
{
id: 2,
article: {"date" : "01-02-2022", "title" : "title6", "summary" : "summary6"}
},
{
id: 3,
article: {"date" : "01-02-2022", "title" : "title7", "summary" : "summary7"}
},
{
id: 1,
article: {"date" : "01-02-2022", "title" : "title5", "summary" : "summary5"}
},
];
const fun = (ar)=>{
const output = ar.reduce((prev, curr) => {
const tmp = prev.find(e => e.id===curr.id);
if (tmp) {
tmp.article.push(curr.article)
} else {
prev.push({
id : curr.id,
article : [curr.article]
});
}
return prev;
}, []);
return output
}
console.log(fun(topics))
I am newbie in angular, facing one issue if somebody helps then it will be appreciable
I have a array of objects like below
signals = [{
'signalID': '123'
},{
'signalID': '233'
},{
'signalID': '333'
},{
'signalID': '433'
},{
'signalID': '533'
},{
'signalID': '633'
},{
'signalID': '733'
}]
I have an object like below
signalOrder = {
333:1,
433:2,
533:3
}
i want to add an property to signals array as orderNo if signalId is matched in signalOrder object else orderNo should be null.
Result expected :
signals = [{
'signalID': '123',
'orderNo':null
},{
'signalID': '233',
'orderNo':null
},{
'signalID': '333',
'orderNo':1
},{
'signalID': '433',
'orderNo':2
},{
'signalID': '533',
'orderNo':3
},{
'signalID': '633',
'orderNo':null
},{
'signalID': '733',
'orderNo':null
}]
I hope it should work with javascript map function but don't know how to use it.
You can do it like :
let signals = [{'signalID': '123'},{'signalID': '233'},{'signalID': '333'},{'signalID': '433'},{'signalID': '533'},{'signalID': '633'},{'signalID': '733'}];
let signalOrder = {333:1,433:2,533:3}
let mapped = signals.map(x=>{
return {
signalID:x.signalID,
orderNo:signalOrder[x.signalID]
}
})
console.log(mapped)
You can use Array.map() to create the result you wish. For each signal item, we'll look up the orderNo in the signalOrder object. If not present, we'll set it to null.
const signals = [{ 'signalID': '123' },{ 'signalID': '233' },{ 'signalID': '333' },{ 'signalID': '433' },{ 'signalID': '533' },{ 'signalID': '633' },{ 'signalID': '733' }];
const signalOrder = {
333:1,
433:2,
533:3
}
const result = signals.map(({signalID}) => ({
signalID,
orderNo: signalOrder[signalID] || null
}))
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
This has nothing to do with Angular or Typescript. It could be solved with vanilla JS Array methods.
Here is a method using Array#map, spread syntax, falsy test using OR ||. Attempting signalOrder[signal.signalID] would return undefined for unavailable properties, which is falsy. In these cases, null would be used.
Try the following
const signals = [{ 'signalID': '123' },{ 'signalID': '233' },{ 'signalID': '333' },{ 'signalID': '433' },{ 'signalID': '533' },{ 'signalID': '633' },{ 'signalID': '733' }]
const signalOrder = { 333:1, 433:2, 533:3 }
const result = signals.map(signal => ({
...signal,
orderNo: signalOrder[signal.signalID] || null
}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
signals = [{
'signalID': '123'
},{
'signalID': '233'
},{
'signalID': '333'
},{
'signalID': '433'
},{
'signalID': '533'
},{
'signalID': '633'
},{
'signalID': '733'
}];
signalOrder = {
333:1,
433:2,
533:3
};
signals.map(obj => {
if(obj.signalID in signalOrder){
obj.orderNo = signalOrder[obj.signalID]
}
else{
obj.orderNo = null
}
})
console.log(signals)
You are right. We can use JS map function to resolve this. I have verified the below code, you can try this:
signals.map(obj => {
if(obj.signalID in signalOrder){
obj.orderNo = signalOrder[obj.signalID]
}
else{
obj.orderNo = null
}
})
This question already has answers here:
Sort array of objects by string property value
(57 answers)
Closed 2 years ago.
I have an array of objects with several key value pairs, and I need to sort them based on 'name':
[
{
"name" : "RAM",
"value" : "12 GB"
},
{
"name" : "Operating System",
"value" : "Android"
},
{
"name" : "Model",
"value" : "Google Pixel XL"
},
{
"name" : "Color",
"value" : "Red"
}
]
The result I want is as follows.
[
{
"name" : "Color",
"value" : "Red"
},
{
"name" : "Model",
"value" : "Google Pixel XL"
},
{
"name" : "Operating System",
"value" : "Android"
},
{
"name" : "RAM",
"value" : "12 GB"
}
]
What's the most efficient way to do so?
Thanks in advance for your reply
you could use: https://underscorejs.org/#sortBy, if you just import this specific method (rather than the whole library) it's tiny and perfect for this
their example:
var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];
_.sortBy(stooges, 'name');
=> [{name: 'curly', age: 60}, {name: 'larry', age: 50}, {name: 'moe', age: 40}];
You can do something like this.
function sortByKey(array, key) {
return array.sort(function(a, b) {
var x = a[key]; var y = b[key];
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
});
}
This question already has answers here:
merge two object arrays with Angular 2 and TypeScript?
(6 answers)
Closed 2 years ago.
I have 2 list of maps like
payload1 = [
{
'series': 'abc',
'value' : 123,
'date' : '2020-06-22'
}, {
'series': 'efg',
'value' : 789,
'date' : '2020-06-21'
} ]
and
payload2 = [
{
'series': 'xyz',
'value' : 234,
'date' : '2020-06-22'
}, {
'series': 'tuv',
'value' : 23442,
'date' : '2020-06-21'
} ]
How can I genrate a new list of map like
payload = [
{
'series': 'abc',
'value' : 123,
'date' : '2020-06-22'
}, {
'series': 'efg',
'value' : 789,
'date' : '2020-06-21'
}, {
'series': 'xyz',
'value' : 234,
'date' : '2020-06-22'
}, {
'series': 'tuv',
'value' : 23442,
'date' : '2020-06-21'
} ]
Basically i need to concatenate 2 list of maps to create a new one. is there any way to do this with less iteration??
You can use the spread operator "..." to merge the elements of two objects or arrays into one.
let payload = [...payload1, ...payload2]
You may use the Array.concat() function.
let payload1 = [
{
'series': 'abc',
'value' : 123,
'date' : '2020-06-22'
}, {
'series': 'efg',
'value' : 789,
'date' : '2020-06-21'
} ];
let payload2 = [
{
'series': 'xyz',
'value' : 234,
'date' : '2020-06-22'
}, {
'series': 'tuv',
'value' : 23442,
'date' : '2020-06-21'
} ];
let payload = payload1.concat(payload2);
console.log(payload);