2

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!

3 Answers 3

3

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)

Sign up to request clarification or add additional context in comments.

9 Comments

Nice use of set
set is the only way to add or update a value in a Map so by nice I take it you mean appropriate?
Thank you for the very quick response! This worked, and I will be learning from it. I appreciate it.
@Sascha Open the actual browser console.
@iota - Thanks, I didn't know that (except from the better formatting) the console make a difference to what here is displayed.
|
0

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
},{});

Comments

0

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.