Recreate the Json by identifying the missing values - javascript

I have a Json data that I need adjust before sending it to my component. My Json is as below. I need to identify the missing fields and move the below ones up.
[{
"Id": "a",
"ColumnLocation": "0",
"RowLocation": "0"
}, {
"Id": "b",
"ColumnLocation": "0",
"RowLocation": "1"
},
{
"Id": "4",
"ColumnLocation": "0",
"RowLocation": "3"
},
{
"Id": "c",
"ColumnLocation": "1",
"RowLocation": "0"
}, {
"Id": "d",
"ColumnLocation": "1",
"RowLocation": "2"
}, {
"Id": "e",
"ColumnLocation": "2",
"RowLocation": "0"
},
{
"Id": "e",
"ColumnLocation": "2",
"RowLocation": "2"
}]
My required Json is:
[{
"Id": "a",
"ColumnLocation": "0",
"RowLocation": "0"
}, {
"Id": "b",
"ColumnLocation": "0",
"RowLocation": "1"
},
{
"Id": "4",
"ColumnLocation": "0",
"RowLocation": "2"
},
{
"Id": "c",
"ColumnLocation": "1",
"RowLocation": "0"
}, {
"Id": "d",
"ColumnLocation": "1",
"RowLocation": "1"
}, {
"Id": "e",
"ColumnLocation": "2",
"RowLocation": "0"
},
{
"Id": "e",
"ColumnLocation": "2",
"RowLocation": "1"
}]
Here after (0,0), (0,1), property (0,2) is missing so I need to move it up and make it (0,2).. Same way after(1,0), property(1,1) is missing so it has to be (1,1).
I tried writing a custom function for this, but couldn't able to achieve it, so thought any map function that fits this scenario
I am getting gadgets information from the API. In some cases, some gadgets might be missing, so I need to pull there location up and draw the gadgets.
this.userService.getGadgets(id).subscribe(gadgets => { this.res = gadgets.map(function (v) { return v.ColumnLocation; });
// required logic ************/
for (let gadget of gadgets) {
this.dashboardsText = "";
switch (gadget.Name) {

You could store the last column and row, then check if it is not the same column, then reset row counter.
Then check if RowLocation is equal to row counter and if not set the new value.
Finally increment row counter.
var array = [{ Id: "a", ColumnLocation: "0", RowLocation: "0" }, { Id: "b", ColumnLocation: "0", RowLocation: "1" }, { Id: "4", ColumnLocation: "0", RowLocation: "3" }, { Id: "c", ColumnLocation: "1", RowLocation: "0" }, { Id: "d", ColumnLocation: "1", RowLocation: "2" }, { Id: "e", ColumnLocation: "2", RowLocation: "0" }, { Id: "e", ColumnLocation: "2", RowLocation: "2" }];
array.forEach(function (col, row) {
return function (o) {
if (col !== o.ColumnLocation) {
col = o.ColumnLocation;
row = 0;
}
if (+o.RowLocation !== row) {
o.RowLocation = row.toString();
}
row++;
}
}());
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could use global variables instead if the closure, maybe this works for you.
var array = [{ Id: "a", ColumnLocation: "0", RowLocation: "0" }, { Id: "b", ColumnLocation: "0", RowLocation: "1" }, { Id: "4", ColumnLocation: "0", RowLocation: "3" }, { Id: "c", ColumnLocation: "1", RowLocation: "0" }, { Id: "d", ColumnLocation: "1", RowLocation: "2" }, { Id: "e", ColumnLocation: "2", RowLocation: "0" }, { Id: "e", ColumnLocation: "2", RowLocation: "2" }],
col,
row;
array.forEach(function (o) {
if (col !== o.ColumnLocation) {
col = o.ColumnLocation;
row = 0;
}
if (+o.RowLocation !== row) {
o.RowLocation = row.toString();
}
row++;
});
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Array.prototype.move = function (old_index, new_index) {
if (new_index >= this.length) {
var k = new_index - this.length;
while ((k--) + 1) {
this.push(undefined);
}
}
this.splice(new_index, 0, this.splice(old_index, 1)[0]);
};
var array, i;
array = [{"Id": "a","ColumnLocation": "0","RowLocation": "0"}, {
"Id": "b","ColumnLocation": "0", "RowLocation": "1"}]
i = array.length;
while (i--) {
if (!array[i].ColumnLocation) {
array.move(i, i+1);
}

Related

Preparing JSON tree structure from a JSON javascript

am looking for a JSON tree from a plain JSON.
below is the Input and expected output json.
the input json doesnt have any order
There can be multiple items at each level and each item can have n number of childrens.
leafFlag = 0 means no children
leafFlag = 1 means has chidlren
path is the property which tells where the item will be placed
The expectedOutputJson needs to be placed in a table to display level wise data
var inputJson = [
{
"level": "1",
"leafFlag": "1",
"path":"p123",
"name":"food"
},
{
"level": "1",
"leafFlag": "1",
"path":"r125",
"name":"car"
},
{
"level": "2",
"leafFlag": "0",
"path":"p123/p345",
"name":"apple"
},
{
"level": "2",
"leafFlag": "1",
"path":"p123/p095",
"name":"banana"
},
{
"level": "3",
"leafFlag": "0",
"path":"p123/p095/p546",
"name":"grapes"
},
{
"level": "2",
"leafFlag": "1",
"path":"r125/yhes",
"name":"tata"
},
]
var expectedOutput = [
{
"level": "1",
"leafFlag": "1",
"path": "p123",
"name": "food",
"children": [
{
"level": "2",
"leafFlag": "0",
"path": "p123/p345",
"name": "apple"
},
{
"level": "2",
"leafFlag": "1",
"path": "p123/p095",
"name": "banana",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "p123/p095/p546",
"name": "grapes"
}
]
}
]
},
{
"level": "1",
"leafFlag": "1",
"path": "r125",
"name": "car",
"children": [
{
"level": "2",
"leafFlag": "1",
"path": "r125/yhes",
"name": "tata",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "r125/yhes/sdie",
"name": "Range Rover"
}
]
},
{
"level": "2",
"leafFlag": "0",
"path": "r125/theys",
"name": "suzuki"
}
]
}
]
i tried the below code but not able to proceed further
private prepareTreeStructure = (inputJson) => {
const treeFormat = (key, index, result) => {
if (key.indexOf('/') === -1) {
result = [...result, ...d[key]];
} else {
result.forEach((item, index) => {
let splitKeyArray = key.split('/');
splitKeyArray.forEach((splitItem, splitIndex) => {
if (splitKeyArray.indexOf(item.path) !== -1) {
if (!item['children']) {
item['children'] = [];
}
if (splitKeyArray.length === splitIndex + 1) {
result[index]['children'] = [...result[index]['children'], ...d[key]];
}
}
});
if (splitKeyArray.indexOf(item.path) !== -1) {
if (!result[index]['children']) {
result[index]['children'] = [];
}
result[index]['children'] = [...result[index]['children'], ...d[key]];
}
});
}
return result;
}
const d = inputJson.reduce((acc, ele) => {
if (!acc[ele.path]) {
acc[ele.path] = [];
}
acc[ele.path].push(ele);
return acc;
}, {});
console.log('dddd ', d);
this.result = [];
Object.keys(d).forEach((key, index) => {
this.result = treeFormat(key, index, this.result);
console.log('out ', this.result);
})
}
prepareTreeStructure(inputJson);
I think you're looking for something like this, works for an n number of levels:
var inputJson = [
{
"level": "1",
"leafFlag": "1",
"path":"p123",
"name":"food"
},
{
"level": "1",
"leafFlag": "1",
"path":"r125",
"name":"car"
},
{
"level": "2",
"leafFlag": "0",
"path":"p123/p345",
"name":"apple"
},
{
"level": "2",
"leafFlag": "1",
"path":"p123/p095",
"name":"banana"
},
{
"level": "3",
"leafFlag": "0",
"path":"p123/p095/p546",
"name":"grapes"
},
{
"level": "2",
"leafFlag": "1",
"path":"r125/yhes",
"name":"tata"
}
]
And the actual code:
var output = [];
inputJson = inputJson.sort((a, b) => (parseInt(a.level) > parseInt(b.level)) ? 1 : -1)
inputJson.forEach(v => {
if (v.level == "1") {
v.children = [];
output.push(v);
}
else {
pathValues = v.path.split("/");
pathValues.pop();
var node = null;
var fullPath = "";
pathValues.forEach(p => {
fullPath = fullPath === "" ? p : fullPath + "/" + p;
node = (node == null ? output : node.children).find(o => o.path === fullPath);
})
node.children = node.children || [];
node.children.push(v);
}
})
console.log(output)
See the jsfiddle: https://jsfiddle.net/L984bo6x/8/
var inputJson = [
{
"level": "1",
"leafFlag": "1",
"path":"p123",
"name":"food"
},
{
"level": "1",
"leafFlag": "1",
"path":"r125",
"name":"car"
},
{
"level": "2",
"leafFlag": "0",
"path":"p123/p345",
"name":"apple"
},
{
"level": "2",
"leafFlag": "1",
"path":"p123/p095",
"name":"banana"
},
{
"level": "3",
"leafFlag": "0",
"path":"p123/p095/p546",
"name":"grapes"
},
{
"level": "2",
"leafFlag": "0",
"path":"r125/yhes",
"name":"tata"
},
]
var expectedOutput = [
{
"level": "1",
"leafFlag": "1",
"path": "p123",
"name": "food",
"children": [
{
"level": "2",
"leafFlag": "0",
"path": "p123/p345",
"name": "apple"
},
{
"level": "2",
"leafFlag": "1",
"path": "p123/p095",
"name": "banana",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "p123/p095/p546",
"name": "grapes"
}
]
}
]
},
{
"level": "1",
"leafFlag": "1",
"path": "r125",
"name": "car",
"children": [
{
"level": "2",
"leafFlag": "1",
"path": "r125/yhes",
"name": "tata",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "r125/yhes/sdie",
"name": "Range Rover"
}
]
},
{
"level": "2",
"leafFlag": "0",
"path": "r125/theys",
"name": "suzuki"
}
]
}
]
const groupByLevels = inputJson => {
var levelsObj = {};
inputJson.forEach(ele => {
if (ele.level === "1") {
if (!levelsObj["1"]) {
levelsObj["1"] = [];
}
levelsObj["1"].push(ele)
} else {
if (!levelsObj[ele.level]) {
levelsObj[ele.level] = {};
}
var parKey = ele.path.substr(0, ele.path.lastIndexOf('/'));
if (!levelsObj[ele.level][parKey]) {
levelsObj[ele.level][parKey] = [];
}
levelsObj[ele.level][parKey].push(ele);
}
})
return levelsObj;
}
const mergeByGroups = (currLevelArr, groupJSON) => {
currLevelArr.forEach(ele => {
if (ele.leafFlag == "0") {
return ele;
}
let nextLevel = parseInt(ele.level) + 1 + ""
let nextLevelArr = groupJSON[nextLevel][ele.path];
mergeByGroups(nextLevelArr, groupJSON)
ele.children = nextLevelArr;
})
}
const constructOutput = groupJSON => {
mergeByGroups(groupJSON["1"], groupJSON);
return groupJSON["1"];
}
console.log(JSON.stringify(constructOutput(groupByLevels(inputJson)), null, 4));

javascript: Object and array manipulation i

Hey guys i really strongly to convert this array , can somebody help me out?
[ {
"0":{"name":"a","available":"12","onOrder":"0",},
"1"{"name":"b","available":"3","onOrder":"0","},
"2"{"name":"c","available":"0","onOrder":"3"},
"3"{"name":"d","available":"2","onOrder":"2"}
} ]
how to map or convert to
[ {"name":"a","available":"12","onOrder":"0",},
{"name":"b","available":"3","onOrder":"0","},
{"name":"c","available":"0","onOrder":"3"},
{"name":"d","available":"2","onOrder":"2"}
]
The original example input has a few syntactical issues so I am not sure as to what the "array" and its elements look like. Making an assumption to make it syntactically compliant with the fewest modifications leads to the array in the working example below. Based on that input, using Object.values is the simplest way to get the desired output.
const arr = [{
"0": {
"name": "a",
"available": "12",
"onOrder": "0",
},
"1": {
"name": "b",
"available": "3",
"onOrder": "0"
},
"2": {
"name": "c",
"available": "0",
"onOrder": "3"
},
"3": {
"name": "d",
"available": "2",
"onOrder": "2"
}
}];
console.log(Object.values(arr[0]));
EDIT: Updated to show ES2015 compatible solution
const arr = [{
"0": {
"name": "a",
"available": "12",
"onOrder": "0",
},
"1": {
"name": "b",
"available": "3",
"onOrder": "0"
},
"2": {
"name": "c",
"available": "0",
"onOrder": "3"
},
"3": {
"name": "d",
"available": "2",
"onOrder": "2"
}
}];
console.log(Object.keys(arr[0]).map(k => arr[0][k]));
You can use Array.prototype.map()
const arr = [
{ "0": {"name":"a","available":"12","onOrder":"0"} },
{ "1": {"name":"b","available":"3","onOrder":"0" } },
{ "2": {"name":"c","available":"0","onOrder":"3" } },
{ "3": {"name":"d","available":"2","onOrder":"2"} }
];
const newArr = arr.map((item, index) => {
return item[index];
});
console.log(newArr);
More complex solution will be
const arr = [{
'0': {
'name': 'a',
'available': '12',
'onOrder': '0'
},
'1': {
'name': 'b',
'available': '3',
'onOrder': '0'
},
'2': {
'name': 'c',
'available': '0',
'onOrder': '3'
},
'3': {
'name': 'd',
'available': '2',
'onOrder': '2'
}
}]
const arr2 = arr.reduce((arr, item) => [...arr, ...Object.values(item)], [])
console.log(arr2)

Biggest number of a field in Json data [duplicate]

This question already has answers here:
Finding the max value of an attribute in an array of objects
(21 answers)
Closed 5 years ago.
My Json data is as below
[{
"Name": "PieChart",
"Id": "1",
"ColumnLocation": "0",
"RowLocation": "0"
}, {
"Name": "Calendar",
"Id": "2",
"ColumnLocation": "1",
"RowLocation": "0"
}, {
"Name": "FavouriteFilter",
"Id": "3",
"ColumnLocation": "2",
"RowLocation": "0"
}, {
"Name": "FilterResults",
"Id": "4",
"ColumnLocation": "0",
"RowLocation": "1"
}, {
"Name": "Watched",
"Id": "5",
"ColumnLocation": "1",
"RowLocation": "1"
}]
I need to find the highest number of the ColumnLocation of the above data. I need that information because I can draw my dashboard based on this number of columns.
Reduce:
const a = [{
"Name": "PieChart",
"Id": "1",
"ColumnLocation": "0",
"RowLocation": "0"
}, {
"Name": "Calendar",
"Id": "2",
"ColumnLocation": "1",
"RowLocation": "0"
}, {
"Name": "FavouriteFilter",
"Id": "3",
"ColumnLocation": "2",
"RowLocation": "0"
}, {
"Name": "FilterResults",
"Id": "4",
"ColumnLocation": "0",
"RowLocation": "1"
}, {
"Name": "Watched",
"Id": "5",
"ColumnLocation": "1",
"RowLocation": "1"
}];
const r = a.reduce((a, c) => (c.ColumnLocation > a) ? c.ColumnLocation : a, 0);
console.log(r)
You could map every ColumnLocation key and use Math.max function to get the highest value.
var data = [{"Name":"PieChart","Id":"1","ColumnLocation":"0","RowLocation":"0"},{"Name":"Calendar","Id":"2","ColumnLocation":"1","RowLocation":"0"},{"Name":"FavouriteFilter","Id":"3","ColumnLocation":"2","RowLocation":"0"},{"Name":"FilterResults","Id":"4","ColumnLocation":"0","RowLocation":"1"},{"Name":"Watched","Id":"5","ColumnLocation":"1","RowLocation":"1"}],
res = data.map(v => v.ColumnLocation);
//console.log(Math.max.apply(Math, res));
console.log(Math.max(...res));
Chucking out there a solution using the lodash maxBy function:
const maxColumnLocation = _.maxBy(data, 'ColumnLocation').ColumnLocation;

Objects nested in objects iteration?

I want to write a function that will find the Categoy[3].options[3].label and matches it to the letter "D".
How do I iterate through the nested objects below to go through the TagCategory.options and search for the option that matches to the letter "D"? If it matches the letter "D", it should return true.
"Category":
[
{
"field": "A",
"options": [
{"tag": "100", "value": "yes"}
],
"label": "Red"
},
{
"field": "tanks",
"type": true,
"options": [
{"tag_value": "4", "value": "4", "label": "A"},
{"tag_value": "3", "value": "3", "label": "B"},
{"tag_value": "2", "value": "2", "label": "C"},
{"tag_value": "1", "value": "1", "label": "D"},
{"tag_value": "5", "value": "5", "label": "E"}
],
"label": "Tanks"
}
]
Something like this?
function findLabel(arr, label) {
for (var i in arr) {
const options = arr[i].options;
const find = options.find(o => o.label == label);
if (find) {
return true;
}
}
return false;
}
const test = findLabel(Category, "D");
Category is your array
function check(category, letter){
var obj;
var optionObj;
for(var i = 0; i < category.length; i++){
obj = Category[i];
options = obj.options;
for(var j = 0; j < options.length; j++){
optionObj = option[j];
if(optionObj.label === letter) return true;
}
}
return false;
}
Here is a rough example of what I mean by a nested for loop.
category = {...}; // your object above
for (i in category) {
field = category[i];
for (option_i in field.options) {
// This is the nested for loop - called thus because it's inside one.
if (field.options[option_i].label == "D"){
return true;
}
}
}
You can use Array.prototype.some()
let optionHasLabelDBool = obj.Category.some(({options}) =>
options.some(({label}) => label === "D"));
let obj = {
"Category":
[{
"field": "A",
"options": [{
"tag": "100",
"value": "yes"
}],
"label": "Red"
},
{
"field": "tanks",
"type": true,
"options": [{
"tag_value": "4",
"value": "4",
"label": "A"
}, {
"tag_value": "3",
"value": "3",
"label": "B"
}, {
"tag_value": "2",
"value": "2",
"label": "C"
}, {
"tag_value": "1",
"value": "1",
"label": "D"
}, {
"tag_value": "5",
"value": "5",
"label": "E"
}],
"label": "Tanks"
}
]
};
let optionHasLabelD = obj.Category.some(({options}) => options.some(({label}) => label === "D"));
console.log(optionHasLabelD);
Using a function, without arrow function or object destructing
function checkOption(array, prop, key, value) {
return array.some(function(obj) {
return obj[prop].some(function(match) {
return match[key] === value;
});
});
}
let optionHasLabelDBool = checkOption(obj.Category, "options", "label", "D");
let obj = {
"Category": [{
"field": "A",
"options": [{
"tag": "100",
"value": "yes"
}],
"label": "Red"
},
{
"field": "tanks",
"type": true,
"options": [{
"tag_value": "4",
"value": "4",
"label": "A"
}, {
"tag_value": "3",
"value": "3",
"label": "B"
}, {
"tag_value": "2",
"value": "2",
"label": "C"
}, {
"tag_value": "1",
"value": "1",
"label": "D"
}, {
"tag_value": "5",
"value": "5",
"label": "E"
}],
"label": "Tanks"
}
]
};
function checkOption(array, prop, key, value) {
return array.some(function(obj) {
return obj[prop].some(function(match) {
console.log(match[key], value, match[key] === value);
return match[key] === value;
});
});
}
let optionHasLabelDBool = checkOption(obj.Category, "options", "label", "D");
console.log(optionHasLabelDBool);

Nested recursive array loop

Was wondering if anyone knows of a way to use lodash, or vanilla JS to achieve this small problem?
I have this starting object:
{
"1": {
"null": {
"2": {
"3": {
"6": {
"7": "c"
},
"null": {
"null": {
"5": "b"
}
}
}
}
}
},
"8": {
"10": "e",
"null": {
"9": "d"
}
}
}
Each level (horizontally) means something. So level 1 is of type A, level 2 is of type B, 3 of type A, 4 of type B and so forth. So it alternates.
Is there a nice and simply way to "collapse" this object to look something like this:
[
{
"type": "A",
"label": "1",
"children": [
{
"type": "A",
"label": "2",
"children": [
{
"type": "B",
"label": "3",
"children": [
{
"type": "A",
"label": "6",
"children": [
{
"type": "A",
"label": "7",
"value": "c"
}
]
},
{
"type": "A",
"label": "8",
"children": [
{
"type": "A",
"label": "5",
"value": "b"
}
]
}
]
}
]
}
]
},
{
"type": "A",
"label": "8",
"children": [
{
"type": "B",
"label": "10",
"value": "e"
},
{
"type": "A",
"label": "9",
"value": "d"
}
]
}
]
In essence annotating each level with what type it is, and nesting its children.
Here is the code
function transformObj(obj, level) {
level = level || 1;
var result = _(obj).transform(function(result, value, key) {
var obj = {
type: (level % 2 === 0) ? 'B' : 'A',
label: key
};
if (key === 'null') {
result.push(transformObj(value, level+1));
} else {
if (_.isObject(value)) {
obj.children = transformObj(value, level+1);
} else {
obj.value = value;
}
result.push(obj);
}
}, [])
.flatten()
.value();
return result;
}
Here is the output
[
{
"type": "A",
"label": "1",
"children": [
{
"type": "A",
"label": "2",
"children": [
{
"type": "B",
"label": "3",
"children": [
{
"type": "A",
"label": "6",
"children": [
{
"type": "B",
"label": "7",
"value": "c"
}
]
},
{
"type": "A",
"label": "5",
"value": "b"
}
]
}
]
}
]
},
{
"type": "A",
"label": "8",
"children": [
{
"type": "B",
"label": "10",
"value": "e"
},
{
"type": "A",
"label": "9",
"value": "d"
}
]
}
]
This should do the trick:
var source = {
"1": {
"null": {
"2": {
"3": {
"6": {
"7": "c"
},
"null": {
"null": {
"5": "b"
}
}
}
}
}
},
"8": {
"10": "e",
"null": {
"9": "d"
}
}
};
function collapse(obj, parent, level){
var result = parent || [];
level = level || 0;
for(prop in obj){
var item = obj[prop];
var build = {
type : level % 2 ? "B" : "A",
label : prop
//, level : level
}
if(typeof item == 'object'){
build.children = [];
collapse(item, build.children, level + 1);
} else {
build.value = item;
}
result.push(build);
}
return result;
}
var output = collapse(source);
var result = JSON.stringify(output, null, ' ');
console.log(result);
var elem = document.getElementById("result");
elem.innerHTML = result;
<pre id="result"></pre>
function doIt(data){
return _.chain(data)
.transform(function(result, value, key){
if(key !== 'null'){
var type = _.parseInt(key) % 2 === 1 ? 'A' : 'B';
if(_.isObject(value) && !_.includes(_.keys(value), 'prop1')){
result.push({
type: type,
label: key,
children: doIt(value)
});
} else {
result.push({
type: type,
label: key,
value: value
});
}
} else {
if(_.isObject(value)){
result.push(doIt(value));
}
}
}, [])
.flatten()
.value();
}
var result = doIt(data);
result is
[
{
"type": "A",
"label": "1",
"children": [
{
"type": "B",
"label": "2",
"children": [
{
"type": "A",
"label": "3",
"children": [
{
"type": "B",
"label": "6",
"children": [
{
"type": "A",
"label": "7",
"value": "c"
}
]
},
{
"type": "A",
"label": "5",
"value": "b"
}
]
}
]
}
]
},
{
"type": "B",
"label": "8",
"children": [
{
"type": "B",
"label": "10",
"value": "e"
},
{
"type": "A",
"label": "9",
"value": "d"
}
]
}
]

Categories