17

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.

7
  • Post a sample input and output please. Commented Jun 11, 2018 at 16:52
  • @amrendersingh Added some test-data and the output it gives Commented Jun 11, 2018 at 16:57
  • We need to know what output you want though. What are you expecting the code to do. Commented Jun 11, 2018 at 17:01
  • @KingKerosin do you want to map iso to ranking points? Commented Jun 11, 2018 at 17:03
  • @amrendersingh. Nope. Iso to rank (which is calculated by the sorting of the rankingpoints). Updated the question to show what I want Commented Jun 11, 2018 at 17:03

3 Answers 3

22

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

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

1 Comment

Thanks. Going with the reduce-style as I am a fan of one-liners ;) The order is the point here, as I just want it to show the rank. But it is okay doing this by the idx parameter on the before sorted Array.
6

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

Comments

0

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

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.