Add new object based on key:value - javascript

I have an object, I want to add a new object before each object based on did value. What I tried is below, but it not what I want, it add for each item, and also it turned into array.
let obj = {
"district": [{
"id": 1,
"uid": 1,
"type": 3,
"pid": 0,
"cid": 0,
"did": 1,
"name": "text 1"
},
{
"id": 2,
"uid": 2,
"type": 3,
"pid": 0,
"cid": 0,
"did": 2,
"name": "text 2"
},
{
"id": 3,
"uid": 3,
"type": 3,
"pid": 0,
"cid": 0,
"did": 2,
"name": "text 3"
},
{
"id": 4,
"uid": 4,
"type": 3,
"pid": 0,
"cid": 0,
"did": 3,
"name": "text 4"
},
{
"id": 5,
"uid": 5,
"type": 3,
"pid": 0,
"cid": 0,
"did": 3,
"name": "text 5"
},
{
"id": 6,
"uid": 6,
"type": 3,
"pid": 0,
"cid": 0,
"did": 0, // should not add object before this becaus did is 0
"name": "text 6"
}
]
}
var result = obj.district.map(function(el) {
if(el.did > 0){
var o = Object.assign({}, obj.district);
o.divider = {
"dv": true,
"name": 'divider ' + el.did
};
return o;
}
})
console.log(result)
Add new object if did value is not null or 0, kinda > 0. the result should be like this:
let obj = {
"district": [{
"dv": true,
"name": "divider 1"
}, {
"id": 1,
"uid": 1,
"type": 3,
"pid": 0,
"cid": 0,
"did": 1,
"name": "text 1"
},
{
"dv": true,
"name": "divider 2"
},
{
"id": 2,
"uid": 2,
"type": 3,
"pid": 0,
"cid": 0,
"did": 2,
"name": "text 2"
},
{
"id": 3,
"uid": 3,
"type": 3,
"pid": 0,
"cid": 0,
"did": 2,
"name": "text 3"
},
{
"dv": true,
"name": "divider 3"
},
{
"id": 4,
"uid": 4,
"type": 3,
"pid": 0,
"cid": 0,
"did": 3,
"name": "text 4"
},
{
"id": 5,
"uid": 5,
"type": 3,
"pid": 0,
"cid": 0,
"did": 3,
"name": "text 5"
},
{
"id": 6,
"uid": 6,
"type": 3,
"pid": 0,
"cid": 0,
"did": 0, // should not add object before this becaus did is 0
"name": "text 6"
}
]
}
console.log(obj)
It should add before object with common did id, for example if there is 5 item with did 2, it should just add new object once, not for each item. also name of new value should be based on did id, divider 1, divider 2 or ..

Try this:
var lastDivider;
var result = {
district: []
}
obj.district.forEach(function(el) {
if (el.did > 0 && lastDivider !== el.did) {
result.district.push({
"dv": true,
"name": 'divider ' + el.did
});
lastDivider = el.did;
}
result.district.push([Object.assign({}, el)]);
});

Related

Converting Array of dot notation strings to nested Json-Object

I have the following problem. I'd like to convert an array of strings in dot notation to a nested json object.
example input: obj = {"project1.foo.a" : "value", "project1.foo.b" : "value","project1.bar" : "value", "project2.foo.a" : "value", "project2.foo.b" : "value", "project2.foo.c" : "value", "project2.foo.bar" : "value"};
desired output:
{
"id": 0,
"title": "Projects",
"has_children": 1,
"level": 1,
"value":"string",
"children": [
{
"id": 1,
"title": "Project 1",
"has_children": true,
"level": 2,
"value":"string",
"children": [
{
"id": 11,
"title": "foo",
"has_children": true,
"level": 3,
"value":"string",
"children": [
{
"id": 111,
"title": "a",
"has_children": false,
"level": 4,
"value":"string",
"children": [
]
},
{
"id": 112,
"title": "b",
"has_children": false,
"level": 4,
"value":"string",
"children": [
]
}
]
},
{
"id": 12,
"title": "bar",
"has_children": false,
"level": 3,
"value":"string",
"children": [
]
}
]
},
{
"id": 2,
"title": "Project 2",
"has_children": true,
"level": 2,
"value":"string",
"children": [
{
"id": 21,
"title": "foo",
"has_children": true,
"level": 3,
"value":"string",
"children": [
{
"id": 211,
"title": "a",
"has_children": false,
"level": 4,
"value":"string",
"children": [
]
},
{
"id": 212,
"title": "b",
"has_children": false,
"level": 4,
"value":"string",
"children": [
]
},
{
"id": 213,
"title": "c",
"has_children": false,
"level": 4,
"value":"string",
"children": [
]
}
]
},
{
"id": 22,
"title": "bar",
"has_children": false,
"level": 3,
"value":"string",
"children": [
]
}
]
}
]
}
There are great functions to unflatten the example object, e. g. with lodash, but I'm not able to add the descendants recursively into the childrens array.
example code:
const unflatten = (flattedObject) => {
let result = {};
_.keys(flattedObject).forEach(function (key, value){
_.set(result, key, flattedObject[key]);
})
return result;
}
console.log(unflatten(obj));
Maybe someone knows a good/neat or at least working approach to do this. :D I want to feed this plugin with the data https://travistidwell.com/jquery.treeselect.js/.
Related posts: How to populate jquery treeselect widget?
How to unflatten a JavaScript object in a daisy-chain/dot notation into an object with nested objects and arrays?

Build flat array with levels from tree array in javascript

I have the following array tree in javascript:
[
{
"id": 1,
"parentId": null,
"description": "Item 1",
"value": 0,
"children": [
{
"id": 2,
"parentId": 1,
"description": "Item 1.1",
"value": 0,
"children": [
{
"id": 3,
"parentId": 2,
"description": "Item 1.1.1",
"value": 0,
"children": []
}
]
}
]
},
{
"id": 4,
"parentId": null,
"description": "Item 2",
"value": 0,
"children": [
{
"id":5,
"parentId": 4,
"description": "Item 2.1",
"value": 0,
"children": []
}
]
}
]
I want to turn it into a flat one with it's levels, like this (see level attribute):
[
{
"id":1,
"parentId": null,
"description":"Item 1",
"value":0,
"level": "1"
},
{
"id":2,
"parentId": 1,
"description":"Item 1.1",
"value":0,
"level": "1.1"
},
{
"id":3,
"parentId": 2,
"description":"Item 1.1.1",
"value":0,
"level": "1.1.1"
},
{
"id":4,
"parentId": null,
"description":"Item 2",
"value":0,
"level": "2"
},
{
"id":5,
"parentId": 4,
"description":"Item 2.1",
"value":0,
"level": "2.1"
}
]
What's the best way to do this regardless of depth?
PS: I have the flat one too, but without "level" attribute and the proposal is to add this attribute based on parentId and sort list by it, like following:
Item 1
Item 1.1
Item 1.1.1
Item 2
Item 2.1
If you don't want to limit the solution by the depth of the array, then I suggest not to use recursion.
const solution = data => {
const stack = data.map((item, index) => ({ ...item, level: `${index + 1}` }))
const result = []
while (stack.length) {
const item = stack.pop()
const { children, ...restItem } = item
stack.push(...item.children.map((child, index) => ({ ...child, level: `${item.level}.${index + 1}` })))
result.push(restItem)
}
return result
}
const data = [
{
"id": 1,
"parentId": null,
"description": "Item 1",
"value": 0,
"children": [
{
"id": 2,
"parentId": 1,
"description": "Item 1.1",
"value": 0,
"children": [
{
"id": 3,
"parentId": 2,
"description": "Item 1.1.1",
"value": 0,
"children": []
}
]
}
]
},
{
"id": 4,
"parentId": null,
"description": "Item 2",
"value": 0,
"children": [
{
"id":5,
"parentId": 4,
"description": "Item 2.1",
"value": 0,
"children": []
}
]
}
]
console.log(solution(data))
If you recursively loop through your array (assuming that children will always be the key), something like this will work.
const arr = [
{
"id": 1,
"parentId": null,
"description": "Item 1",
"value": 0,
"children": [
{
"id": 2,
"parentId": 1,
"description": "Item 1.1",
"value": 0,
"children": [
{
"id": 3,
"parentId": 2,
"description": "Item 1.1.1",
"value": 0,
"children": []
}
]
}
]
},
{
"id": 4,
"parentId": null,
"description": "Item 2",
"value": 0,
"children": [
{
"id":5,
"parentId": 4,
"description": "Item 2.1",
"value": 0,
"children": []
}
]
}
]
const newArray = [];
const flatten = (item, parentIdx) => {
// separate parent from children
item.forEach(({ children, ...child}, idx) => {
// create level
const level = `${parentIdx ? `${parentIdx}.` : ''}${idx + 1}`;
// add parent to new array
newArray.push({...child, level});
// recursively flatten children
flatten(children, level);
})
}
flatten(arr)
console.log(newArray)

How to handle complex tree array and traverse new arrays?

Object index 0:
If select===1, the third-level array length have two select===1, the two-level push to selected:[8,9] and checkedAll:true
the one-level checkedAll:true and push to selected:[7]
Object index 1: Same as above Object index 0
Object index 2:
If select===1, the two-level push to selected:[15], the third-level child array length > two-level array selected length, indeterminate:true
and the one-level indeterminate:true
I am trying to solve the complex json, don't know how to implement the following result array.
The correct result is printed as follows
[{
"id": 1,
"pid": 0,
"name": "a",
"select": 0,
"checkedAll": true,
"indeterminate": false,
"selected": [7],
"child": [{
"id": 7,
"pid": 1,
"name": "a-1",
"select": 1,
"checkedAll": true,
"indeterminate": false,
"selected": [8, 9],
"child": [{
"id": 8,
"pid": 7,
"name": "a-1-2",
"select": 1
},
{
"id": 9,
"pid": 7,
"name": "a-2-2",
"select": 1
}
]
}]
},
{
"id": 2,
"pid": 0,
"name": "b",
"select": 1,
"checkedAll": true,
"indeterminate": false,
"selected": [10],
"child": [{
"id": 10,
"pid": 2,
"name": "b-1",
"select": 1,
"checkedAll": true,
"indeterminate": false,
"selected": [11, 12],
"child": [{
"id": 11,
"pid": 10,
"name": "b-1-1",
"select": 1
},
{
"id": 12,
"pid": 10,
"name": "b-1-2",
"select": 1
}
]
}]
},
{
"id": 3,
"pid": 0,
"name": "c",
"select": 0,
"checkedAll": false,
"indeterminate": true,
"selected": [],
"child": [{
"id": 13,
"pid": 3,
"name": "c-1",
"select": 1,
"checkedAll": false,
"indeterminate": true,
"selected": [15],
"child": [{
"id": 14,
"pid": 13,
"name": "c-1-1",
"select": 0
},
{
"id": 15,
"pid": 13,
"name": "c-1-2",
"select": 1
}
]
}]
}
]
My code:
var result = [{
"id": 1,
"pid": 0,
"name": "a",
"select": 0,
"child": [{
"id": 7,
"pid": 1,
"name": "a-1",
"select": 1,
"child": [{
"id": 8,
"pid": 7,
"name": "a-1-2",
"select": 1
},
{
"id": 9,
"pid": 7,
"name": "a-2-2",
"select": 1
}
]
}]
},
{
"id": 2,
"pid": 0,
"name": "b",
"select": 0,
"child": [{
"id": 10,
"pid": 2,
"name": "b-1",
"select": 0,
"child": [{
"id": 11,
"pid": 10,
"name": "b-1-1",
"select": 1
},
{
"id": 12,
"pid": 10,
"name": "b-1-2",
"select": 1
}
]
}]
},
{
"id": 3,
"pid": 0,
"name": "c",
"select": 0,
"child": [{
"id": 13,
"pid": 3,
"name": "c-1",
"select": 1,
"child": [{
"id": 14,
"pid": 13,
"name": "c-1-1",
"select": 0
},
{
"id": 15,
"pid": 13,
"name": "c-1-2",
"select": 1
}
]
}]
}
]
var selected = []
for (let i = 0; i < result.length; i++) {
const a1 = result[i].child
for (let j = 0; j < a1.length; j++) {
console.log(a1[j].name)
const a2 = a1[j].child
for (let k = 0; k < a2.length; k++) {
if (a1[j].id === a2[k].pid) {
if (a2[k].select === 1) {
console.log(a1[j].id)
console.log(a2[k].name)
console.log('yyyyyyyy', a2[k].id)
}
}
}
}
}
console.log(result)
described as follows
And what about this (not sure if it is possible to change items order), you can click accept under voting arrows in case you like it:
var selected = [], result = input();
for (let i = 0; i < result.length; i++) {
const a1 = result[i].child
for (let j = 0; j < a1.length; j++) {
const a2 = a1[j].child
for (let k = 0; k < a2.length; k++) {
if (a1[j].id === a2[k].pid) {
if (a2[k].select === 1) {
let selected = a1[j].selected || [];
selected.push(a2[k].id)
a1[j].selected = selected;
if (selected.length == a2.length) {
result[i].checkedAll = true;
a1[j].checkedAll = true;
}
result[i].selected = a1[j].id;
}
}
}
result[i].indeterminate = !result[i].checkedAll;
a1[j].indeterminate = !a1[j].checkedAll;
}
}
console.log(JSON.stringify(result, null, 2))
function input() {
return [{
"id": 1,
"pid": 0,
"name": "a",
"select": 0,
"child": [{
"id": 7,
"pid": 1,
"name": "a-1",
"select": 1,
"child": [{
"id": 8,
"pid": 7,
"name": "a-1-2",
"select": 1
},
{
"id": 9,
"pid": 7,
"name": "a-2-2",
"select": 1
}
]
}]
},
{
"id": 2,
"pid": 0,
"name": "b",
"select": 0,
"child": [{
"id": 10,
"pid": 2,
"name": "b-1",
"select": 0,
"child": [{
"id": 11,
"pid": 10,
"name": "b-1-1",
"select": 1
},
{
"id": 12,
"pid": 10,
"name": "b-1-2",
"select": 1
}
]
}]
},
{
"id": 3,
"pid": 0,
"name": "c",
"select": 0,
"child": [{
"id": 13,
"pid": 3,
"name": "c-1",
"select": 1,
"child": [{
"id": 14,
"pid": 13,
"name": "c-1-1",
"select": 0
},
{
"id": 15,
"pid": 13,
"name": "c-1-2",
"select": 1
}
]
}]
}
];
}

Remove child element from a JSON array in PHP / codeigniter

I am getting below json array as and i want to remove the child node "n":[] - when it is empty. (PHP)
INPUT:
[
{
"level": 1,
"id": "101",
"n": [
{
"level": 2,
"id": "102",
"n": [
]
}
]
},
{
"level": 1,
"id": "103",
"n": [
{
"level": 2,
"id": "104",
"n": [
]
},
{
"level": 2,
"id": "105",
"n": [
{
"level": 3,
"id": "106",
"n": [
]
},
{
"level": 3,
"id": "107",
"n": [
{
"level": 4,
"id": "108",
"n": [
{
"level": 5,
"id": "109",
"n": [
]
}
]
}
]
}
]
}
]
},
{
"level": 1,
"id": "110",
"n": [
{
"level": 2,
"id": "111",
"n": [
{
"level": 3,
"id": "112",
"n": [
]
}
]
},
{
"level": 2,
"id": "113",
"n": [
{
"level": 3,
"id": "114",
"n": [
{
"level": 4,
"id": "115",
"n": [
]
}
]
},
{
"level": 3,
"id": "116",
"n": [
{
"level": 4,
"id": "117",
"n": [
]
},
{
"level": 4,
"id": "118",
"n": [
{
"level": 5,
"id": "119",
"n": [
]
},
{
"level": 5,
"id": "120",
"n": [
]
}
]
}
]
}
]
}
]
}
]
OUTPUT:
[
{
"level": 1,
"id": "101",
"n": [
{
"level": 2,
"id": "102"
}
]
},
{
"level": 1,
"id": "103",
"n": [
{
"level": 2,
"id": "104"
},
{
"level": 2,
"id": "105",
"n": [
{
"level": 3,
"id": "106"
},
{
"level": 3,
"id": "107",
"n": [
{
"level": 4,
"id": "108",
"n": [
{
"level": 5,
"id": "109"
}
]
}
]
}
]
}
]
},
{
"level": 1,
"id": "110",
"n": [
{
"level": 2,
"id": "111",
"n": [
{
"level": 3,
"id": "112"
}
]
},
{
"level": 2,
"id": "113",
"n": [
{
"level": 3,
"id": "114",
"n": [
{
"level": 4,
"id": "115"
}
]
},
{
"level": 3,
"id": "116",
"n": [
{
"level": 4,
"id": "117"
},
{
"level": 4,
"id": "118",
"n": [
{
"level": 5,
"id": "119"
},
{
"level": 5,
"id": "120"
}
]
}
]
}
]
}
]
}
]
All the ,"n":[] removed from the json array.
Please help me with some PHP code to get the output from that above input.
Use the recursion, to recursively find the property n which has the value [] and delete them:
function removeEmptyNode(nodes) {
if(!nodes || nodes.length === 0)
return;
nodes.forEach(function(node) {
if(node.n.length === 0) {
delete node.n;
} else {
removeEmptyNode(node.n);
}
});
}
var data = [{
"level": 1,
"id": "101",
"n": [{
"level": 2,
"id": "102",
"n": []
}]
}, {
"level": 1,
"id": "103",
"n": [{
"level": 2,
"id": "104",
"n": []
}, {
"level": 2,
"id": "105",
"n": [{
"level": 3,
"id": "106",
"n": []
}, {
"level": 3,
"id": "107",
"n": [{
"level": 4,
"id": "108",
"n": [{
"level": 5,
"id": "109",
"n": []
}]
}]
}]
}]
}, {
"level": 1,
"id": "110",
"n": [{
"level": 2,
"id": "111",
"n": [{
"level": 3,
"id": "112",
"n": []
}]
}, {
"level": 2,
"id": "113",
"n": [{
"level": 3,
"id": "114",
"n": [{
"level": 4,
"id": "115",
"n": []
}]
}, {
"level": 3,
"id": "116",
"n": [{
"level": 4,
"id": "117",
"n": []
}, {
"level": 4,
"id": "118",
"n": [{
"level": 5,
"id": "119",
"n": []
}, {
"level": 5,
"id": "120",
"n": []
}]
}]
}]
}]
}];
removeEmptyNode(data);
console.log(data);
EDIT:
If you want to do this in PHP, you can convert the above code easily to PHP.
Assuming you have source object in JSON string, you could be able to use this code:
<?php
function removeEmptyNodes(&$nodes) {
if(empty($nodes)) {
return;
}
foreach($nodes as &$node) {
if(empty($node['n'])) {
unset($node['n']);
} else {
removeEmptyNodes($node['n']);
}
}
}
$json = '[{"level":1,"id":"101","n":[{"level":2,"id":"102","n":[]}]},{"level":1,"id":"103","n":[{"level":2,"id":"104","n":[]},{"level":2,"id":"105","n":[{"level":3,"id":"106","n":[]},{"level":3,"id":"107","n":[{"level":4,"id":"108","n":[{"level":5,"id":"109","n":[]}]}]}]}]},{"level":1,"id":"110","n":[{"level":2,"id":"111","n":[{"level":3,"id":"112","n":[]}]},{"level":2,"id":"113","n":[{"level":3,"id":"114","n":[{"level":4,"id":"115","n":[]}]},{"level":3,"id":"116","n":[{"level":4,"id":"117","n":[]},{"level":4,"id":"118","n":[{"level":5,"id":"119","n":[]},{"level":5,"id":"120","n":[]}]}]}]}]}]';
$data = json_decode($json, true);
removeEmptyNodes($data);
print_r(json_encode($data));
?>

Search for related properties in the same object. Javascript

I need help with matching childrens in the same object based on parent ID property....
JSON:
{
"1": {
"id": 1,
"name": "My Crib",
"type": "Home",
"order": 0,
"parent": null
},
"2": {
"id": 2,
"name": "First floor",
"type": "Floor",
"order": 1,
"parent": {
"id": 1,
"url": "http://localhost:8080/rest/areas/1"
}
},
"3": {
"id": 3,
"name": "Garage",
"type": "Garage",
"order": 2,
"parent": {
"id": 1,
"url": "http://localhost:8080/rest/areas/1"
}
},
"4": {
"id": 4,
"name": "Garden",
"type": "Garden",
"order": 3,
"parent": {
"id": 1,
"url": "http://localhost:8080/rest/areas/1"
}
},
"5": {
"id": 5,
"name": "Entrance hall",
"type": "Entrance",
"order": 1,
"parent": {
"id": 2,
"url": "http://localhost:8080/rest/areas/2"
}
},
"6": {
"id": 6,
"name": "Kitchen",
"type": "Kitchen",
"order": 2,
"parent": {
"id": 2,
"url": "http://localhost:8080/rest/areas/2"
}
},
"7": {
"id": 7,
"name": "Living room",
"type": "LivingRoom",
"order": 3,
"parent": {
"id": 2,
"url": "http://localhost:8080/rest/areas/2"
}
},
"8": {
"id": 8,
"name": "Dog house",
"type": "DogHouse",
"order": 1,
"parent": {
"id": 4,
"url": "http://localhost:8080/rest/areas/4"
}
}
}
const mappedAreas = Object.keys(areas).map(function(key) {
const area = areas[key];
const wrappers = statics["test.area.groups"]["wrappers"];
const leafs = statics["test.area.groups"]["leafs"];
if (wrappers.indexOf(area["type"]) > -1) {
//In the array!
//If not a home
if(area["type"] != "Home"){
console.log("floor:")
console.log(area)
//get wrapper childrens
const children = Object.keys(areas).map(function(key) {
const child = areas[key];
if(child["type"] != "Home"){
if(child["parent"]["id"] == area["id"] && leafs.indexOf(child["type"]) > -1){
console.log(child);
//return <Area key={"area_index_"+key} areaData={area} />
}
}
});
console.log("endfloor/")
//return <Area key={"area_index_"+key} areaData={area} />
}
} else {
//Not in the array
}
});
Is there any way to do this better than having one map inside another map?
Basicly I get all areas in one object, and I want to match them with eachother, looking for ["parent"]["id"] to match with ["id"].
Tell me if you need more description.

Categories

Resources