KingKerosin
KingKerosin

Reputation: 3841

Convert js Array to Dictionary/Hashmap

I'm trying to convert an array of objects into a hashmap. I only have some parts of ES6 available and I cannot use Map as well.

The objects in the array are quite simple, e.g. {nation: {name: string, iso: string, scoringPoints: number}. I need to sort them by scoringPoints. I want now a "dictionary" holding the rank by iso -> {[iso:string]:number}.

I already tried (from here (SO))

const dict = sortedData.reduce((prev, curr, index, array) => (
    { ...array, [curr.nation.iso]: ++index }
), {});

But dict turns out to be an Object with indices starting with 0. Hopefully there is just a small thing I don't see. But currently my head is spinning how to convert a simple array into a hashmap-like object. Maybe Array.map?

I should also note that I am using TypeScript which I also had some trouble before when not typed correctly.

const test = [
    { nation: { name: "Germany", iso: "DE", rankingPoints: 293949 } },
    { nation: { name: "Hungary", iso: "HU", rankingPoints: 564161 } },
    { nation: { name: "Serbia", iso: "SR", rankingPoints: 231651 } }
];

const sorted = test.sort((a, b) => a.nation.rankingPoints - b.nation.rankingPoints);
const dict = sorted.reduce((prev, curr, index, array) => ({ ...array, [curr.nation.iso]: ++index }), {});
console.log(JSON.stringify(dict));  

is showing

{
    "0": {
        "nation": {
            "name": "Serbia",
            "iso": "RS",
            "rankingPoints": 231651
        }
    },
    "1": {
        "nation": {
            "name": "Germany",
            "iso": "DE",
            "rankingPoints": 293949
        }
    },
    "2": {
        "nation": {
            "name": "Hungary",
            "iso": "HU",
            "rankingPoints": 564161
        }
    },
    "HU": 3
}

in the console.

As per comments, what I want is a hashmap-like object like

{
    "HU": 1,
    "DE": 2,
    "RS": 3
}

where the property-value is the rank (+1) in the sorted data so I can simply get the rank by accessing dict["DE"] which would return 2.

Upvotes: 17

Views: 54359

Answers (3)

It is also possible to achieve this using Array.map and Object.fromEntries:

const test = [
  { nation: { name: "Germany", iso: "DE", rankingPoints: 293949 } },
  { nation: { name: "Hungary", iso: "HU", rankingPoints: 564161 } },
  { nation: { name: "Serbia", iso: "SR", rankingPoints: 231651 } }
];

const sorted = test.sort((a, b) => a.nation.rankingPoints < b.nation.rankingPoints ? 1 : (a.nation.rankingPoints > b.nation.rankingPoints ? -1 : 0));

const dict = Object.fromEntries(sorted.map((c, index) => [c.nation.iso, index + 1]));

console.log(dict);

Upvotes: 6

Bhavin Sanghvi
Bhavin Sanghvi

Reputation: 36

const test = [
  { nation: { name: "Germany", iso: "DE", rankingPoints: 293949 } },
  { nation: { name: "Hungary", iso: "HU", rankingPoints: 564161 } },
  { nation: { name: "Serbia", iso: "SR", rankingPoints: 231651 } }
];

const sorted = test.sort((a, b) =>  b.nation.rankingPoints - a.nation.rankingPoints);
const dict = sorted.reduce((result, curr, index, array) => ({ ...result, [curr.nation.iso]: ++index }), {});
console.log(JSON.stringify(dict)); 

Upvotes: 0

jspcal
jspcal

Reputation: 51894

Capture the position of each key in your data using forEach or reduce:

const test = [
    { nation: { name: "Germany", iso: "DE", rankingPoints: 293949 } },
    { nation: { name: "Hungary", iso: "HU", rankingPoints: 564161 } },
    { nation: { name: "Serbia", iso: "SR", rankingPoints: 231651 } }
];    

const sorted = test.sort((a, b) => a.nation.rankingPoints - b.nation.rankingPoints);

// Using forEach:

var dict = {}
sorted.forEach((el, index) => dict[el.nation.iso] = sorted.length - index);

// Using reduce:

dict = sorted.reduce(
    (dict, el, index) => (dict[el.nation.iso] = sorted.length - index, dict),
    {}
);

console.log(dict)
console.log("dict['DE'] = ", dict['DE'])

Output:

{
  "SR": 3,
  "DE": 2,
  "HU": 1
}
dict['DE'] =  2

(Note the order of properties is not significant in an object used as a map - if you need a specific order use an array.)

Upvotes: 22

Related Questions