How can I extract objects several layers deep using the map method? - javascript

I'm a trying to access the change order information as seen below to create a list of all the change_order_names. Using the current code I am getting the results I have posted. Will someone show me how I can access the change order information and produce the list?
if (componentType == CHANGE_ORDER_TYPE) {
if (!this.props.data) {
return null;
} else {
const changeList = this.props.data.map(function (result) {
return (result.change_orders);
});
// return resultsList;
console.log(changeList);
}
}
This is the current response from the map method above.
[
[
{
"id":1,
"change_order_name":"change 1",
"project_id":"1",
"cws_change_order_id":"33214324",
"slug":"change-1",
"created_at":null,
"updated_at":null
},
{
"id":2,
"change_order_name":"change 2",
"project_id":"1",
"cws_change_order_id":"3211324",
"slug":"change-2",
"created_at":null,
"updated_at":null
}
],
[
{
"id":3,
"change_order_name":"change 3",
"project_id":"2",
"cws_change_order_id":"3234324",
"slug":"change-3",
"created_at":null,
"updated_at":null
},
{
"id":4,
"change_order_name":"change 4",
"project_id":"2",
"cws_change_order_id":"6234532",
"slug":"change-4",
"created_at":null,
"updated_at":null
}
],
[
{
"id":5,
"change_order_name":"change 5",
"project_id":"3",
"cws_change_order_id":"3124214",
"slug":"change-5",
"created_at":null,
"updated_at":null
}
]
]

This is how I dug down to get get access to the individual change_orders
if (componentType == CHANGE_ORDER_TYPE) {
if (!this.props.data) {
return null;
} else {
const changeList = this.props.data.map(function (result) {
return (result.change_orders);
});
let changeOrdersArr = [];
for (let i = 0; i < changeList.length; i++) {
let inner = changeList[i];
for (let z = 0; z < inner.length; z++) {
changeOrdersArr.push(inner[z])
}
}

It's not entirely clear what your desired output is, but I think you want a single array with all change_orders in it? If this is correct then you can use the reduce function after your current map function:
if (componentType == CHANGE_ORDER_TYPE) {
if (!this.props.data) {
return null;
} else {
const changeList = this.props.data.map(function (result) {
return (result.change_orders);
}).reduce((output, item) => [...output, ...item], []);
// return changeList;
console.log(changeList);
}
}
const mapOutput = [
[
{
"id":1,
"change_order_name":"change 1",
"project_id":"1",
"cws_change_order_id":"33214324",
"slug":"change-1",
"created_at":null,
"updated_at":null
},
{
"id":2,
"change_order_name":"change 2",
"project_id":"1",
"cws_change_order_id":"3211324",
"slug":"change-2",
"created_at":null,
"updated_at":null
}
],
[
{
"id":3,
"change_order_name":"change 3",
"project_id":"2",
"cws_change_order_id":"3234324",
"slug":"change-3",
"created_at":null,
"updated_at":null
},
{
"id":4,
"change_order_name":"change 4",
"project_id":"2",
"cws_change_order_id":"6234532",
"slug":"change-4",
"created_at":null,
"updated_at":null
}
],
[
{
"id":5,
"change_order_name":"change 5",
"project_id":"3",
"cws_change_order_id":"3124214",
"slug":"change-5",
"created_at":null,
"updated_at":null
}
]
];
const change_orders = mapOutput.reduce((orders, arr) => [...orders,...arr],[]);
console.log(change_orders);

Related

Restructure Nested JSON Data And Removing Some Keys

I need to restructure a nested JSON data.
Here is how it looks like:
{
"MainKey1": [
{
"Section1": {
"ParentTag1 Mapped Label": {
"ParentTag1": {
"Tag1 Mapped Label": {
"Tag1": "1234567890"
}
}
}
}
},
{
"Section2": {
"ParentTag1 Mapped Label": {
"ParentTag1": {
"Tag1 Label": {
"Tag1": "111222333444"
},
"Tag2 Label": {
"Tag2": "121212"
},
"Tag3 Label": {
"Tag3": "0987654321"
}
}
}
}
}
],
"MainKey2": [
{
"Section1": {
"ParentTag1 Mapped Label": {
"ParentTag1": {
"Tag1 Mapped Label": {
"Tag1": "1234567890"
}
}
}
}
}
]
}
And this is a sample of the converted JSON:
{
MainKey: [
{
Section1: [
{
ParentTag1: [
{ Tag1: "1234567890" }
]
}
]
},
{
Section2: [
{
ParentTag1: [
{ Tag1: "111222333444" },
{ Tag2: "121212" },
{ Tag3: "0987654321" }
]
}
]
}
],
MainKey2: [
{
Section1: [
{
ParentTag1 : [
{ Tag1: "1234567890" }
]
}
]
}
]
}
Rules:
Everything inside a MainKey (outermost keys, could be any name) should be an array
All labels should be stripped (as the label could be any name, without the actual word "Label", we can determine if it is a label based on the depth level. Since the JSON will have the label as the parent and the actual "tag" as a child.
Here is what I currently have (it is a mess, sorry!)
function convertJson (jsonObj) {
const mainKeys = Object.keys(jsonObj)
let output = {}
for (let i = 0; i < mainKeys.length; i++) {
const mainKey = mainKeys[i]
let result = []
output[mainKey] = result
for (let j = 0; j < jsonObj[mainKey].length; j++) {
const innerObj = {...jsonObj[mainKey][j]}
const sectionName = Object.keys(innerObj)[0]
const sectionObj = {}
sectionObj[sectionName] = []
const index = result.push(sectionObj) - 1
parseObj(innerObj[sectionName], result[index], 0) // if I change 2nd param to: result, it generates incorrect output
}
}
console.log(output)
}
function parseObj (innerObj, result, depthCount) {
for (var key in innerObj) {
if (typeof innerObj[key] === "object") {
if (depthCount % 2 === 1) {
const parentObj = {}
parentObj[key] = []
result.push(parentObj)
depthCount++
parseObj(innerObj[key], parentObj[key], depthCount)
} else {
depthCount++
parseObj(innerObj[key], result, depthCount)
}
} else {
const keyValuePairObj = {}
keyValuePairObj[key] = innerObj[key]
result.push(keyValuePairObj)
}
}
return result
}
convertJson(json)
But it generates an error:
Uncaught TypeError: result.push is not a function
Now if I change line 90 from:
parseObj(innerObj[sectionName], result[index], 0)
to:
parseObj(innerObj[sectionName], result, 0)
Here is incorrect output:
{
"MainKey1": [
{
"Section1": []
},
{
"ParentTag1": [
{
"Tag1": "1234567890"
}
]
},
{
"Section2": []
},
{
"ParentTag1": [
{
"Tag1": "111222333444"
},
{
"Tag2 Label": [
{
"Tag2": "121212"
}
]
},
{
"Tag3": "0987654321"
}
]
}
],
"MainKey2": [
{
"Section1": []
},
{
"Tag1": "1234567890"
}
]
}
And here is my fiddle:
https://jsfiddle.net/kzaiwo/L4avxmyd/36/
Thanks a lot! Appreciate any help!

frame array of recursive json object from an another array of objects

i have an array of objects of the below format
each with a unique 'sub-task' entry, each of this sub-task is to be embedded as a children element of each unique 'task' from the 'tasks' array
[
{
"sub-task":"abc",
"task":"alpha1"},
{
"sub-task":"def",
"task":"alpha1"},
{
"sub-task":"ijkl",
"task":"proto"},
{
"sub-task":"mno",
"task":"def"},
{
"sub-task":"qrs",
"task":"proto"},
{
"sub-task":"asdf",
"task":"mno"},
]
i was trying to frame an another array of below format
[
{
"name":"alpha1",
"children":[
{
"name":"abc"
},
{
"name":"def",
"children":[
{
"name":"mno"
}
]
}
]
},
{
"name":"proto",
"children":[
{
"name":"ijkl"
},
{
"name":"qrs",
"children":[
{
"name":"asdf"
}
]
}
]
}
]
i was trying of below logic, but ended up with no solution...
var treeData = [];
for( var ele of tasks){
recurOn(treeData,ele);
}
function recurOn(arr,obj){
if(arr.length == 0){
treeData.push({name:obj.parentGroup,children:[{name:obj.groupName}]})
//console.log(treeData);
return 1;
}else {
for(var item of treeData){
if(item.name == obj.parentGroup){
//console.log('item: ', item);
item.children.push({name:obj.groupName});
break;
}
else {
treeData.push(recurOn([],obj))
}
}
return 1;
}
}
//console.log(treeData);
//console.log(result);
Since the no of levels an elements holds is not known i was unable to fix for a logic
Use a map to store object reference.
let input = [
{ "sub-task": "abc", "task": "alpha1" },
{ "sub-task": "def", "task": "alpha1" },
{ "sub-task": "ijkl", "task": "proto" },
{ "sub-task": "mno", "task": "def" },
{ "sub-task": "qrs", "task": "proto" },
{ "sub-task": "asdf", "task": "mno" },
];
let map = new Map, result = [];
input.forEach(({ ["sub-task"]: name, task }) => {
let node = map.get(task), child = { name, children: [] };
if (!node) {
map.set(task, node = { name: task, children: [] });
result.push(node);
}
map.set(name, child);
node.children.push(child);
})
console.log(result);

Filter objects using filter

I have array of object like below:
pages= [
{
"id":1,
"name":"name1",
"languages":[
{
"id":1,
"lang":"en"
},
{
"id":2,
"lang":"de"
}
]
},
{
"id":2,
"name":"name2",
"languages":[
{
"id":1,
"lang":"en"
},
{
"id":2,
"lang":"de"
}
]
},
{
"id":3,
"name":"name3",
"languages":[
{
"id":1,
"lang":"en"
}
]
}
]
And array of languages(these will be set by clicking on checkboxes) is as below:
selectedLanguages=['en'];
Now, I want to filter the main array depending upon the selectedLanguages values. I have tried with below code:
pages.filter(page => {
var present = false;
page.languages.map(l => {
if(selectedLanguages.includes(l.lang)) {
present = true;
}
});
if(present) {
return page;
}
})
Desired output: if selectedLanguages = ['en'] then all items from pages, if de then first 2 elements.
It works but I am curious if I can make it better?
Any suggestions would be helpful :) Thanks.
You can use a combination of Array#Filter, Array#find and Array#includes for that :
let pages= [
{
"id":1,
"name":"name1",
"languages":[
{
"id":1,
"lang":"en"
},
{
"id":2,
"lang":"de"
}
]
},
{
"id":2,
"name":"name2",
"languages":[
{
"id":1,
"lang":"en"
},
{
"id":2,
"lang":"fr"
}
]
}
]
let selectedLanguages=['fr'];
let result = pages.filter(e => e.languages.find(l => selectedLanguages.includes(l.lang)));
console.log(result);
Rather than trying to create an intermediate array with .map, it would be better to simply check if some of the languages include a lang matching the selectedLanguages:
const pages=[{"id":1,"name":"name1","languages":[{"id":1,"lang":"en"},{"id":2,"lang":"de"}]},{"id":2,"name":"name2","languages":[{"id":1,"lang":"en"},{"id":2,"lang":"de"}]}]
const selectedLanguages=['en'];
console.log(
pages.filter(({ languages }) => (
languages.some(({ lang }) => selectedLanguages.includes(lang))
))
)
You can use filter() with indexOf() check for the selectedLanguages array:
var pages= [
{
"id":1,
"name":"name1",
"languages":[
{
"id":1,
"lang":"en"
},
{
"id":2,
"lang":"de"
}
]
},
{
"id":2,
"name":"name2",
"languages":[
{
"id":1,
"lang":"en"
},
{
"id":2,
"lang":"de"
}
]
},
{
"id":3,
"name":"name3",
"languages":[
{
"id":5,
"lang":"us"
},
{
"id":6,
"lang":"de"
}
]
}
];
var selectedLanguages=['en'];
var res = pages.filter((page) => {
var languageFound = page.languages.find(language => selectedLanguages.indexOf(language.lang) !== -1);
if(languageFound){
return page;
}
});
console.log(res);

How to change values in array which meet criteria via JS

I have a big JSON data, this is a small part:
users = [{
"name": "alex",
"id":123,
"surname":"xx",
"status":"activated",
tarriff: {
"id":1,
"name":"free"
}
},
{
"name": "tom",
"id":124,
"surname":"henry",
"status":"activated",
tarriff: {
"id":1,
"name":"free"
}
},
{
"name": "tom",
"id":125,
"surname":"henry",
"status":"archived",
tarriff: {
"id":1,
"name":"free"
}
}]
I need to change value 'activated' to 'deactivated', 'archived' to 'active' in whole array.
I think I need to use for loop, but I don't know how to properly write it.
Use the Array prototype map function :
users = users.map(function(u) {
if (u.status == 'activated') u.status = 'deactivated'
if (u.status == 'archived') u.status = 'active'
return u
})
Update. A faster approach.
var counter, item;
for (counter in users) {
item = users[counter];
if (item.status == 'activated') item.status = 'deactivated'
if (item.status == 'archived') item.status = 'active'
}
You cannot do it faster or more narrow.
Try the following with array's map().
var users = [{
"name": "alex",
"id":123,
"surname":"xx",
"status":"activated",
tarriff: {
"id":1,
"name":"free"
}
},
{
"name": "tom",
"id":124,
"surname":"henry",
"status":"activated",
tarriff: {
"id":1,
"name":"free"
}
},
{
"name": "tom",
"id":125,
"surname":"henry",
"status":"archived",
tarriff: {
"id":1,
"name":"free"
}
}];
var res = users.map(function(item){
if(item.status == 'activated')
item.status = 'deactivated';
if(item.status == 'archived')
item.status = 'active';
return item;
});
console.log(res);
this is a possible way (Array#extras):
function changeUserStatus(status) {
// 'activated' to 'deactivated', 'archived' to 'active'
switch (status) {
case 'activated':
return 'deactivated';
case 'archived':
return 'active';
default:
return status;
}
}
function changeStatus(users) {
return users.map(function(user) {
return Object.assign({}, user, {
status: changeUserStatus(user.status),
});
});
}
var users = [{
"name": "alex",
"id":123,
"surname":"xx",
"status":"activated",
tarriff: {
"id":1,
"name":"free"
}
},
{
"name": "tom",
"id":124,
"surname":"henry",
"status":"activated",
tarriff: {
"id":1,
"name":"free"
}
},
{
"name": "tom",
"id":125,
"surname":"henry",
"status":"archived",
tarriff: {
"id":1,
"name":"free"
}
}];
const edited = changeStatus(users);
console.log('edited', edited);
Do not know if your intentions about to mutate original object or just return a new array of objects. But below code might give you an inspiration.
function changeValue(obj, k, vold, vnew) {
if (obj.hasOwnProperty(k) && obj[k] == vold) {
obj[k] = vnew
}
return obj;
}
then,
users
.map(e => changeValue(e, 'status', 'activated', 'deactivated'))
.map(e => changeValue(e, 'status', 'archived', 'active'));

Create a JSON reading recursively from another unknown JSON with Javascript

I'd like to read recursively all nodes from a generic JSON (so I'm not asking for a script that handles exclusively this kind of structure) and while reading I would to create another JSON in a structure like this (the example is just an excerpt):
[
{
"name":"AgreementOffer",
"size":20000000,
"children":[
{
"name":"Name",
"size":2000000,
"children":[
{
"name":"1cap",
"size":90
}
]
},
{
"name":"Context",
"size":2000000,
"children":[
{
"name":"AgreementInitiator",
"size":200,
"children":[
{
"name":"$SPECS-CUSTOMER",
"size":100
}
]
},
{
"name":"AgreementInitiator",
"size":200,
"children":[
{
"name":"$SPECS-CUSTOMER",
"size":100
}
]
},
{
"name":"AgreementResponder",
"size":200,
"children":[
{
"name":"$SPECS-APPLICATION",
"size":100
}
]
},
{
"name":"AgreementResponder",
"size":200,
"children":[
{
"name":"$SPECS-APPLICATION",
"size":100
}
]
},
{
"name":"ServiceProvider",
"size":200,
"children":[
{
"name":"AgreementResponder",
"size":100
}
]
},
{
"name":"ServiceProvider",
"size":200,
"children":[
{
"name":"AgreementResponder",
"size":100
}
]
},
{
"name":"ExpirationTime",
"size":200,
"children":[
{
"name":"2014-02-02T06:00:00",
"size":100
}
]
},
{
"name":"ExpirationTime",
"size":200,
"children":[
{
"name":"2014-02-02T06:00:00",
"size":100
}
]
},
{
"name":"TemplateName",
"size":200,
"children":[
{
"name":"Y2-APP-TEMPLATE",
"size":100
}
]
},
{
"name":"TemplateName",
"size":200,
"children":[
{
"name":"Y2-APP-TEMPLATE",
"size":100
}
]
}
]
}
]
}
]
So, I ask you for a script be able to handle a generic JSON (unknown structure and deep) and create another JSON written with the above structure.
Thanks!
Try it at https://jsfiddle.net/zqkdq5mf/1/
function AppendObject(obj) {
//console.log(JSON.stringify(obj) + ":" + JSON.stringify(obj).length);
var Summary = null;
for (var propertyName in obj) {
if (typeof obj[propertyName] === "object" && !Summary) {
Summary = { name: propertyName.toString(), size: JSON.stringify(obj).length, children: [] };
for (var childPropertyName in obj[propertyName]) {
var Child = {};
Child[childPropertyName] = obj[propertyName][childPropertyName];
Summary.children[Summary.children.length] = AppendObject(Child);
}
break;
} else if (!Summary) Summary = { key: propertyName, value: obj[propertyName], size: JSON.stringify(obj).length };
}
return Summary;
}
function Convert() {
$(".data").empty();
var ParsedJSON = $.parseJSON($("textarea").val()),
ObjectArray = [],
Summaries = [];
if (!(ParsedJSON instanceof Array)) ObjectArray[0] = ParsedJSON;
else ObjectArray = ParsedJSON;
for (var i = 0; i < ObjectArray.length; i++) Summaries[Summaries.length] = AppendObject(ObjectArray[i]);
$(".data").text(JSON.stringify(Summaries));
}

Categories