Reputation: 119
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!
Upvotes: 2
Views: 77
Reputation: 4616
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);
Upvotes: 0
Reputation: 15530
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)
Upvotes: 3
Reputation: 3260
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
},{});
Upvotes: 0