Optimizing nested for loop algorithm, Javascript - javascript

I am using the pokemon API to build a fun little informational app. I specifically want to have a section detailing the damage relationships of a pokemon. I currently retrieve and format the data as such:
Array [
Object {
"double_damage_from": Array [
Object {
"name": "flying",
"url": "https://pokeapi.co/api/v2/type/3/",
},
Object {
"name": "poison",
"url": "https://pokeapi.co/api/v2/type/4/",
},
Object {
"name": "bug",
"url": "https://pokeapi.co/api/v2/type/7/",
},
Object {
"name": "fire",
"url": "https://pokeapi.co/api/v2/type/10/",
},
Object {
"name": "ice",
"url": "https://pokeapi.co/api/v2/type/15/",
},
],
"double_damage_to": Array [
Object {
"name": "ground",
"url": "https://pokeapi.co/api/v2/type/5/",
},
Object {
"name": "rock",
"url": "https://pokeapi.co/api/v2/type/6/",
},
Object {
"name": "water",
"url": "https://pokeapi.co/api/v2/type/11/",
},
],
"half_damage_from": Array [
Object {
"name": "ground",
"url": "https://pokeapi.co/api/v2/type/5/",
},
Object {
"name": "water",
"url": "https://pokeapi.co/api/v2/type/11/",
},
Object {
"name": "grass",
"url": "https://pokeapi.co/api/v2/type/12/",
},
Object {
"name": "electric",
"url": "https://pokeapi.co/api/v2/type/13/",
},
],
"half_damage_to": Array [
Object {
"name": "flying",
"url": "https://pokeapi.co/api/v2/type/3/",
},
Object {
"name": "poison",
"url": "https://pokeapi.co/api/v2/type/4/",
},
Object {
"name": "bug",
"url": "https://pokeapi.co/api/v2/type/7/",
},
Object {
"name": "steel",
"url": "https://pokeapi.co/api/v2/type/9/",
},
Object {
"name": "fire",
"url": "https://pokeapi.co/api/v2/type/10/",
},
Object {
"name": "grass",
"url": "https://pokeapi.co/api/v2/type/12/",
},
Object {
"name": "dragon",
"url": "https://pokeapi.co/api/v2/type/16/",
},
],
"name": "grass",
"no_damage_from": Array [],
"no_damage_to": Array [],
},
Object {
"double_damage_from": Array [
Object {
"name": "ground",
"url": "https://pokeapi.co/api/v2/type/5/",
},
Object {
"name": "psychic",
"url": "https://pokeapi.co/api/v2/type/14/",
},
],
"double_damage_to": Array [
Object {
"name": "grass",
"url": "https://pokeapi.co/api/v2/type/12/",
},
Object {
"name": "fairy",
"url": "https://pokeapi.co/api/v2/type/18/",
},
],
"half_damage_from": Array [
Object {
"name": "fighting",
"url": "https://pokeapi.co/api/v2/type/2/",
},
Object {
"name": "poison",
"url": "https://pokeapi.co/api/v2/type/4/",
},
Object {
"name": "bug",
"url": "https://pokeapi.co/api/v2/type/7/",
},
Object {
"name": "grass",
"url": "https://pokeapi.co/api/v2/type/12/",
},
Object {
"name": "fairy",
"url": "https://pokeapi.co/api/v2/type/18/",
},
],
"half_damage_to": Array [
Object {
"name": "poison",
"url": "https://pokeapi.co/api/v2/type/4/",
},
Object {
"name": "ground",
"url": "https://pokeapi.co/api/v2/type/5/",
},
Object {
"name": "rock",
"url": "https://pokeapi.co/api/v2/type/6/",
},
Object {
"name": "ghost",
"url": "https://pokeapi.co/api/v2/type/8/",
},
],
"name": "poison",
"no_damage_from": Array [],
"no_damage_to": Array [
Object {
"name": "steel",
"url": "https://pokeapi.co/api/v2/type/9/",
},
],
},
]
What I want to do is format it like this.
DamageMap: Map {
"double_damage_from" => Array [
"flying",
"poison",
"bug",
"fire",
"ice",
"ground",
"psychic",
],
"double_damage_to" => Array [
"ground",
"rock",
"water",
"grass",
"fairy",
],
"half_damage_from" => Array [
"ground",
"water",
"grass",
"electric",
"fighting",
"poison",
"bug",
"fairy",
],
"half_damage_to" => Array [
"flying",
"poison",
"bug",
"steel",
"fire",
"grass",
"dragon",
"ground",
"rock",
"ghost",
],
"no_damage_from" => Array [],
"no_damage_to" => Array [
"steel",
],
}
The data is formatted into this map with no duplicate types. This is my current solution.
const keys = [
"double_damage_from",
"double_damage_to",
"half_damage_from",
"half_damage_to",
"no_damage_from",
"no_damage_to",
];
const damageMap = new Map();
for (let i = 0; i < results.length; ++i) {
for (let j = 0; j < keys.length; ++j) {
if (!damageMap.has(keys[j])) {
damageMap.set(keys[j], []);
}
const val = damageMap.get(keys[j]);
const curr = results[i][keys[j]];
for (let k = 0; k < curr.length; ++k) {
if (val.indexOf(curr[k].name) === -1) {
val.push(curr[k].name);
}
}
damageMap.set(keys[j], val);
}
}
return damageMap;
};
It is utterly atrocious... I know this. My problem is that any attempt at optimizing it has so far failed. I have tried using combinations of map and reduce functions to no avail. If anybody can take a look at this and optimize it, it would be greatly appreciated!

You may use Array.prototype.reduce() together with Array.prototype.forEach() instead:
const src = [{"double_damage_from":[{"name":"flying","url":"https://pokeapi.co/api/v2/type/3/",},{"name":"poison","url":"https://pokeapi.co/api/v2/type/4/",},{"name":"bug","url":"https://pokeapi.co/api/v2/type/7/",},{"name":"fire","url":"https://pokeapi.co/api/v2/type/10/",},{"name":"ice","url":"https://pokeapi.co/api/v2/type/15/",},],"double_damage_to":[{"name":"ground","url":"https://pokeapi.co/api/v2/type/5/",},{"name":"rock","url":"https://pokeapi.co/api/v2/type/6/",},{"name":"water","url":"https://pokeapi.co/api/v2/type/11/",},],"half_damage_from":[{"name":"ground","url":"https://pokeapi.co/api/v2/type/5/",},{"name":"water","url":"https://pokeapi.co/api/v2/type/11/",},{"name":"grass","url":"https://pokeapi.co/api/v2/type/12/",},{"name":"electric","url":"https://pokeapi.co/api/v2/type/13/",},],"half_damage_to":[{"name":"flying","url":"https://pokeapi.co/api/v2/type/3/",},{"name":"poison","url":"https://pokeapi.co/api/v2/type/4/",},{"name":"bug","url":"https://pokeapi.co/api/v2/type/7/",},{"name":"steel","url":"https://pokeapi.co/api/v2/type/9/",},{"name":"fire","url":"https://pokeapi.co/api/v2/type/10/",},{"name":"grass","url":"https://pokeapi.co/api/v2/type/12/",},{"name":"dragon","url":"https://pokeapi.co/api/v2/type/16/",},],"name":"grass","no_damage_from":[],"no_damage_to":[],},{"double_damage_from":[{"name":"ground","url":"https://pokeapi.co/api/v2/type/5/",},{"name":"psychic","url":"https://pokeapi.co/api/v2/type/14/",},],"double_damage_to":[{"name":"grass","url":"https://pokeapi.co/api/v2/type/12/",},{"name":"fairy","url":"https://pokeapi.co/api/v2/type/18/",},],"half_damage_from":[{"name":"fighting","url":"https://pokeapi.co/api/v2/type/2/",},{"name":"poison","url":"https://pokeapi.co/api/v2/type/4/",},{"name":"bug","url":"https://pokeapi.co/api/v2/type/7/",},{"name":"grass","url":"https://pokeapi.co/api/v2/type/12/",},{"name":"fairy","url":"https://pokeapi.co/api/v2/type/18/",},],"half_damage_to":[{"name":"poison","url":"https://pokeapi.co/api/v2/type/4/",},{"name":"ground","url":"https://pokeapi.co/api/v2/type/5/",},{"name":"rock","url":"https://pokeapi.co/api/v2/type/6/",},{"name":"ghost","url":"https://pokeapi.co/api/v2/type/8/",},],"name":"poison","no_damage_from":[],"no_damage_to":[{"name":"steel","url":"https://pokeapi.co/api/v2/type/9/",},],},],
result = src.reduce((acc, o) => {
Object.keys(o).forEach(key => {
if(Array.isArray(o[key])){
const match = acc.get(key),
items = o[key].map(({name}) => name)
match ?
match.push(...items) :
acc.set(key, items)
}
})
return acc
}, new Map)
console.log(result)

Does this work out?
I didn't know what to call each subelement from the main values array so thing is what i used. But this just digs into there and pulls out the name from each of the sublevel elements and tallies them up.
I didn't worry about uniqueness but you could (after concat) add a uniq clean up thing.
// where `values` is your initial data structure
const damageMap = values.reduce((memo, thing) => {
Object.keys(thing).forEach(key => {
if (key !== 'name') {
memo[key] = memo[key] || []
memo[key] = memo[key].concat(
thing[key].map(({name}) => name))
}
})
return memo
},{});

Using Array.reduce for collecting the data, Array#forEach to iterate over the elements and Object.entries to get key/values from the object.
let map = arr.reduce((acc, cur) => {
Object.entries(cur).forEach(([key, values]) => {
if (!acc[key] && key !=='name') {
acc[key] = [];
}
if (typeof(values)=== 'object') {
values.forEach(({name}) => {
acc[key].push(name);
});
}
});
return acc;
}, {});
Here for playing arround https://jsfiddle.net/h8kL5gp9/ or try this (with the hole code):
let arr = [
{
"double_damage_from": [
{
"name": "flying",
"url": "https://pokeapi.co/api/v2/type/3/",
},
{
"name": "poison",
"url": "https://pokeapi.co/api/v2/type/4/",
},
{
"name": "bug",
"url": "https://pokeapi.co/api/v2/type/7/",
},
{
"name": "fire",
"url": "https://pokeapi.co/api/v2/type/10/",
},
{
"name": "ice",
"url": "https://pokeapi.co/api/v2/type/15/",
},
],
"double_damage_to": [
{
"name": "ground",
"url": "https://pokeapi.co/api/v2/type/5/",
},
{
"name": "rock",
"url": "https://pokeapi.co/api/v2/type/6/",
},
{
"name": "water",
"url": "https://pokeapi.co/api/v2/type/11/",
},
],
"half_damage_from": [
{
"name": "ground",
"url": "https://pokeapi.co/api/v2/type/5/",
},
{
"name": "water",
"url": "https://pokeapi.co/api/v2/type/11/",
},
{
"name": "grass",
"url": "https://pokeapi.co/api/v2/type/12/",
},
{
"name": "electric",
"url": "https://pokeapi.co/api/v2/type/13/",
},
],
"half_damage_to": [
{
"name": "flying",
"url": "https://pokeapi.co/api/v2/type/3/",
},
{
"name": "poison",
"url": "https://pokeapi.co/api/v2/type/4/",
},
{
"name": "bug",
"url": "https://pokeapi.co/api/v2/type/7/",
},
{
"name": "steel",
"url": "https://pokeapi.co/api/v2/type/9/",
},
{
"name": "fire",
"url": "https://pokeapi.co/api/v2/type/10/",
},
{
"name": "grass",
"url": "https://pokeapi.co/api/v2/type/12/",
},
{
"name": "dragon",
"url": "https://pokeapi.co/api/v2/type/16/",
},
],
"name": "grass",
"no_damage_from": [],
"no_damage_to": [],
},
{
"double_damage_from": [
{
"name": "ground",
"url": "https://pokeapi.co/api/v2/type/5/",
},
{
"name": "psychic",
"url": "https://pokeapi.co/api/v2/type/14/",
},
],
"double_damage_to": [
{
"name": "grass",
"url": "https://pokeapi.co/api/v2/type/12/",
},
{
"name": "fairy",
"url": "https://pokeapi.co/api/v2/type/18/",
},
],
"half_damage_from": [
{
"name": "fighting",
"url": "https://pokeapi.co/api/v2/type/2/",
},
{
"name": "poison",
"url": "https://pokeapi.co/api/v2/type/4/",
},
{
"name": "bug",
"url": "https://pokeapi.co/api/v2/type/7/",
},
{
"name": "grass",
"url": "https://pokeapi.co/api/v2/type/12/",
},
{
"name": "fairy",
"url": "https://pokeapi.co/api/v2/type/18/",
},
],
"half_damage_to": [
{
"name": "poison",
"url": "https://pokeapi.co/api/v2/type/4/",
},
{
"name": "ground",
"url": "https://pokeapi.co/api/v2/type/5/",
},
{
"name": "rock",
"url": "https://pokeapi.co/api/v2/type/6/",
},
{
"name": "ghost",
"url": "https://pokeapi.co/api/v2/type/8/",
},
],
"name": "poison",
"no_damage_from": [],
"no_damage_to": [
{
"name": "steel",
"url": "https://pokeapi.co/api/v2/type/9/",
},
],
},
];
let map = arr.reduce((acc, cur) => {
Object.entries(cur).forEach(([key, values]) => {
if (!acc[key] && key !=='name') {
acc[key] = [];
}
if (typeof(values)=== 'object') {
values.forEach(({name}) => {
acc[key].push(name);
});
}
});
return acc;
}, {});
console.log(map);

Related

javascript extract and convert into new array

I have the following array
[ {
"contactId": "a87d096gd5fuop",
"firstName": "John Doe",
"registrationTypes": {
"selectedOptions": [
{
}
],
"subTotal": 1620.003
},
"foo1": {
"selectedOptions": [
],
"subTotal": 0
},
"events": {
"selectedOptions": [
{
"id": "1",
"name": "T1",
"value": "4550006:3",
},
{
"id": "2",
"name": "T2",
"value": "4550005:3",
},
{
"id": "3",
"name": "T3",
"value": "4550003:3",
}
],
"subTotal": 135.003
},
"freeNetworkingFunctions": {
},
"total": 1755.0059999999999
},
{
"contactId": "a097f",
"firstName": "David",
"registrationTypes": {
"selectedOptions": [
{}
],
"subTotal": 899.998
},
"foo1": {
"selectedOptions": [
],
"subTotal": 0
},
"member": {
"selectedOptions": [
{
}
],
"subTotal": 228.8
},
"events": {
"selectedOptions": [
{
"id": "4",
"name": "T4",
"value": "4550002:2",
},
{
"id": "5",
"name": "T5",
"value": "4550001:2",
},
{
"id": "6",
"name": "T6",
"value": "4550003:2",
}
],
"subTotal": 135.003
},
"total": 1263.801
}
]
From the above array, I want to extract events, loop all the data and get only values. So my new array should be something like this:
[ {
"contactId": "a87d096gd5fuop",
"firstName": "John Doe",
"registrationTypes": {
"selectedOptions": [
{
}
],
"subTotal": 1620.003
},
"foo1": {
"selectedOptions": [
],
"subTotal": 0
},
"events": [
"4550006:3"
"4550005:3",
"4550003:3",
],
},
"freeNetworkingFunctions": {
},
"total": 1755.0059999999999
},
{
"contactId": "a097f",
"firstName": "David",
"registrationTypes": {
"selectedOptions": [
{}
],
"subTotal": 899.998
},
"foo1": {
"selectedOptions": [
],
"subTotal": 0
},
"member": {
"selectedOptions": [
{
}
],
"subTotal": 228.8
},
"events": [
"4550004:2"
"4550008:3",
"4550003:3",
],
"subTotal": 135.003
},
"total": 1263.801
}
]
So it should return the original array, however, events value data should be in one array.
var arr = [];
var r(var i=0;i<data.length;i++){
data.push(arr[i].value);
}
var newData = [...data, arr]
However, this doesn't work. Any help would be highly appreciated.
Use map twice - once on the dataset to iterate over the objects, and within that map to get an array of values from the selectedOptions.
const data=[{contactId:"a87d096gd5fuop",firstName:"John Doe",registrationTypes:{selectedOptions:[{}],subTotal:1620.003},foo1:{selectedOptions:[],subTotal:0},events:{selectedOptions:[{id:"1",name:"T1",value:"4550006:3"},{id:"2",name:"T2",value:"4550005:3"},{id:"3",name:"T3",value:"4550003:3"}],subTotal:135.003},freeNetworkingFunctions:{},total:1755.0059999999999},{contactId:"a097f",firstName:"David",registrationTypes:{selectedOptions:[{}],subTotal:899.998},foo1:{selectedOptions:[],subTotal:0},member:{selectedOptions:[{}],subTotal:228.8},events:{selectedOptions:[{id:"4",name:"T4",value:"4550002:2"},{id:"5",name:"T5",value:"4550001:2"},{id:"6",name:"T6",value:"4550003:2"}],subTotal:135.003},total:1263.801}];
const out = data.map(obj => {
// Destructure the selected options from the
// rest of each object
const { events: { selectedOptions }, ...rest } = obj;
// `map` over the options to just get an array of values
const events = selectedOptions.map(option => {
return option.value;
});
// Return a new object with the new events property
// combined with the other properties again
return { ...rest, events };
});
console.log(out);
Additional documentation
Destructuring assignment
Rest parameters
Spread syntax

JavaScript deletes a single item of data from a multidimensional array

Arrays are not fixed, so I think we need to use recursion. Here's the array and my solution :Not implemented yet.
Remove all data where ‘tag’ = 'user'
An array of
var arr = [
{
"name": "ORG_1",
"tag": "org",
"children": [
{
"name": "ORG_1-1",
"tag": "org",
"children": [
{ "name": "USER_1-1-1", "tag": "user" },
{ "name": "USER_1-1-2", "tag": "user" }
]
},
{ "name": "ORG_1-2", "tag": "org", "children": [] },
{ "name": "USER_1-3", "tag": "user" },
{ "name": "USER_1-4", "tag": "user" }
]
},
{
"name": "ORG_2",
"tag": "org",
"children": [
{
"name": "ORG_2-1",
"tag": "org",
"children": [
{ "name": "USER_2-1-1", "tag": "user" },
{ "name": "USER_2-1-2", "tag": "user" }
]
},
{ "name": "ORG_2-2", "tag": "org", "children": [] },
{ "name": "USER_2-3", "tag": "user" },
{ "name": "USER_2-4", "tag": "user" }
]
}
]
I want to delete the object in the array whose 'type' is 'user'.
Here is my code
Code 1
const fun1 = treeList => {
treeList.forEach((item, index) => {
item.tag == 'user' && (treeList.splice(index, 1))
item.children.length && fun1(item.children)
})
}
fun1(arr)
Code 2
const fun2 = treeList => {
treeList = treeList.filter(({ tag }) => tag === 'org')
treeList.forEach((item) => {
item.children.length && fun2(item.children)
})
}
fun2(arr)
This is what I expected, Remove all data where ‘tag’ = 'user'
[
{
"name": "ORG_1",
"tag": "org",
"children": [
{
"name": "ORG_1-1",
"tag": "org",
"children": []
},
{ "name": "ORG_1-2", "tag": "org", "children": [] }
]
},
{
"name": "ORG_2",
"tag": "org",
"children": [
{
"name": "ORG_2-1",
"tag": "org",
"children": []
},
{ "name": "ORG_2-2", "tag": "org", "children": [] }
]
}
]
You can create a function called removeUsers, where you can .map() your array of data, for each object that you map, you can create a new object that contains all the keys from the currently iterated object, along with a new children key that is added only if the currently mapped object has a children key. The value of that children key is a filtered version of the current children array, that removes the objects where the tag is user. You can pass this filtered array of objects into a recursive call to removeUsers to remove the users within those objects' children arrays:
const arr = [ { "name": "ORG_1", "tag": "org", "children": [ { "name": "ORG_1-1", "tag": "org", "children": [ { "name": "USER_1-1-1", "tag": "user" }, { "name": "USER_1-1-2", "tag": "user" } ] }, { "name": "ORG_1-2", "tag": "org", "children": [] }, { "name": "USER_1-3", "tag": "user" }, { "name": "USER_1-4", "tag": "user" } ] }, { "name": "ORG_2", "tag": "org", "children": [ { "name": "ORG_2-1", "tag": "org", "children": [ { "name": "USER_2-1-1", "tag": "user" }, { "name": "USER_2-1-2", "tag": "user" } ] }, { "name": "ORG_2-2", "tag": "org", "children": [] }, { "name": "USER_2-3", "tag": "user" }, { "name": "USER_2-4", "tag": "user" } ] } ];
const removeUsers = arr => arr.map((obj) => ({
...obj,
...(obj.children && {children: removeUsers(obj.children.filter(obj => obj.tag !== "user"))})
}));
console.log(removeUsers(arr));
const filterByTag = (arr, tag) => {
return arr.reduce((acc, item) =>
item.tag !== tag && item.children
? [...acc, { ...item, children: filterByTag(item.children, tag) }]
: acc,
[]);
};
console.log(filterByTag(arr, "user"));

Using undescore.js, i'm trying to format the given input to an expected output

Input:
[{
"dimensions": [{
"name": "Size",
"value": "Size1"
},
{
"name": "Color",
"value": "Color1"
},
{
"name": "Pattern",
"value": "1"
}
],
"link": "link",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size2"
},
{
"name": "Color",
"value": "Color1"
},
{
"name": "Pattern",
"value": "2"
}
],
"link": "link1",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size1"
},
{
"name": "Color",
"value": "Color2"
},
{
"name": "Pattern",
"value": "1"
}
],
"link": "link",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size2"
},
{
"name": "Color",
"value": "Color1"
},
{
"name": "Pattern",
"value": "3"
}
],
"link": "link",
"title": "title"
}]
Expected Output:
{
"levels":3,
"level_1_name":"Size",
"level_2_name":"Color",
"level_3_name":"Pattern",
"data":[
{
"value":"Size1",
"data":[
{
"value":"Color1",
"data":[
{
"value":"1"
}
]
}, {
"value":"Color2",
"data":[
{
"value":"4"
}
]
}
]
}, {
"value":"Size2",
"data":[
{
"value":"Color1",
"data":[
{
"value":"3"
}
]
},
{
"value":"Color2",
"data":[
{
"value":"2"
}
]
}
]
}
]
}
I've tried something like that
for(index=0; index<data[0].dimensions.length - 1; index++) {
let temp = _(data).groupBy(function(o) {
return o.dimensions[index].value
})
let keys = Object.keys(temp)
addData(final, keys, temp)
}
obj["data"] = final
function addData(data, keys, temp) {
if (data && data.length) {
return data.forEach(function(data1){
console.log(data1)
return addData(data1, keys, temp)
})
} else {
let data_arr = []
if (Array.isArray(data)) {
keys.forEach(function(key) {
data.push({
value: key,
data: temp[key]
})
})
} else {
keys.forEach(function(key) {
let data_obj = {}
data_obj['value'] = key
data_obj['data'] = temp[key]
data_arr.push(data_obj)
})
data["data"] = data_arr
}
}
}
I've tried the logic to format as per the expected output. It works with level 2 input set, But the logic written doesn't work for level 3 input data set.
Also It would be helpful if you can suggest any algorithms to sort this problem out.
Thanks in advance!
Here is a fairly compact solution using reduce(). (I've edited the input to match your expected output.)
const source = [{
"dimensions": [{
"name": "Size",
"value": "Size1"
},
{
"name": "Color",
"value": "Color1"
},
{
"name": "Pattern",
"value": "1"
}
],
"link": "link",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size2"
},
{
"name": "Color",
"value": "Color2"
},
{
"name": "Pattern",
"value": "2"
}
],
"link": "link1",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size1"
},
{
"name": "Color",
"value": "Color2"
},
{
"name": "Pattern",
"value": "4"
}
],
"link": "link",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size2"
},
{
"name": "Color",
"value": "Color1"
},
{
"name": "Pattern",
"value": "3"
}
],
"link": "link",
"title": "title"
}];
const output = source.reduce((acc, {dimensions: dims}) => {
const levels = dims.length;
// initialize top-level keys based on first object
if (!acc.hasOwnProperty('levels')) {
acc.levels = levels;
dims.forEach((level, i) => acc[`level_${i+1}_name`] = level.name);
acc.data = [];
}
// iterate over dimension objects and merge with accumulator
let parent = acc.data;
dims.forEach((o, i) => {
let lvlObj = parent.find(e => e.value === o.value);
if (!lvlObj) {
lvlObj = i < levels - 1 ?
{value: o.value, data: []} :
{value: o.value};
parent.push({...lvlObj});
}
parent = lvlObj.data;
});
return acc;
}, {});
console.log(output);

JSON / JavaScript - find matching values, make them into keys and create new, consolidated object

In vanilla JavaScript, how would I find unique locations from this object and make them keys, and place all items with that location as values. (can install lodash if necessary).
So this:
[
{
"item": {
"id": "cat"
},
"location": {
"id": "porch"
}
},
{
"item": {
"id": "dog"
},
"location": {
"id": "porch"
}
},
{
"item": {
"id": "snake"
},
"location": {
"id": "forest"
}
},
{
"item": {
"id": "bird"
},
"location": {
"id": "forest"
}
},
{
"item": {
"id": "beer"
},
"location": {
"id": "fridge"
}
}
]
Becomes this:
[
{
"porch": [
{
"id": "cat"
},
{
"id": "dog"
}
]
},
{
"forest": [
{
"id": "snake"
},
{
"id": "bird"
}
]
},
{
"fridge": [
{
"id": "beer"
}
]
}
]
PEN
// modified desired result
[
{
"location": {
"name": "porch",
"items": [
{
"title": "cat"
},
{
"title": "dog"
}
]
}
},
{
"location": {
"name": "forest",
"items": [
{
"title": "snake"
},
{
"title": "bird"
}
]
}
},
{
"location": {
"name": "fridge",
"items": [
{
"title": "beer"
}
]
}
}
]
let obj = [
{
"item": {
"id": "cat"
},
"location": {
"id": "porch"
}
},
{
"item": {
"id": "dog"
},
"location": {
"id": "porch"
}
},
{
"item": {
"id": "snake"
},
"location": {
"id": "forest"
}
},
{
"item": {
"id": "bird"
},
"location": {
"id": "forest"
}
},
{
"item": {
"id": "beer"
},
"location": {
"id": "fridge"
}
}
]
let result = {};
obj.forEach(({item, location}) => {
if(!result[location.id]) result[location.id] = []
result[location.id].push({title: item.id})
})
result = Object.keys(result).map(key => ({
"location": {
"name": key,
"items": result[key]
}
}))
result contains required output.

Paasing an object into an array of arrays

Have an object that needs to be pass inside the array of source using javascript,throwing an error spec is undefined when using push function. will push function work for this scenario
var a = [
"name": "ben",
"type": "male",
"appType": "human",
"spec": {
"view": "instanceview",
"sink": {
"source": [{
"data": {
"path": "google/path",
"name": "test",
"Id": "11234",
},
"ref": "www.xyz.com",
"id": "isdfjsbfjsfb",
"resourceType": "app"
}
],
},
},
}]
var b = {
"data": {
"path": "google/path",
"name": "goldengate",
"Id": "11234vndslknvlsmnv",
},
"ref": "www.xyz.com",
"id": "6452367e5375",
"resourceType": "app"
}
a.spec.sink.source.push(b);
would expect b to be pushed to source
An array with string keys is not a valid structure, you need to convert a to an object
var a = { // <-- here
"name": "ben",
"type": "male",
"appType": "human",
"spec": {
"view": "instanceview",
"sink": {
"source": [
{
"data": {
"path": "google/path",
"name": "test",
"Id": "11234",
},
"ref": "www.xyz.com",
"id": "isdfjsbfjsfb",
"resourceType": "app"
}
],
},
},
} // <-- here

Categories