Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
112
rated 0 times [  116] [ 4]  / answers: 1 / hits: 21936  / 7 Years ago, mon, april 24, 2017, 12:00:00

Hit this odd bug in my code and I can't figure the way to get a constant time lookup from a Map when using a tuple as my key.



Hopefully this illustrates the issue, and the workaround I'm using now just to get it to work:



hello.ts:



let map: Map<[number, number], number> = new Map<[number, number], number>()
.set([0, 0], 48);

console.log(map.get([0,0])); // prints undefined

console.log(map.get(String([0, 0]))); // compiler: error TS2345: Argument of type
// 'string' is not assignable to parameter of type '[number, number]'.

//the work-around:
map.forEach((value: number, key: [number, number]) => {
if(String(key) === String([0, 0])){
console.log(value); // prints 48
}
})


To compile (transpile?) I'm using:



tsc hello.ts -target es6


tsc version 2.1.6



Tried several things to make the Map.get() method to work, not having much success.


More From » typescript

 Answers
29

In JavaScript (and as an extension, TypeScript), no two arrays are equal except if they refer to the same array (i.e., when changing the elements of one also would change the elements of another). If you create a new array with the same elements, it would not consider it to be equal to any existing one.



Because Maps consider such equality when looking up elements, if you store a value with an array as a key, you can only get the value out again if you pass in the exact same array reference as a key again:



const map: Map<[ number, number], number> = new Map<[ number, number ], number>();

const a: [ number, number ] = [ 0, 0 ];
const b: [ number, number ] = [ 0, 0 ];

// a and b have the same value, but refer to different arrays so are not equal
a === b; // = false

map.set(a, 123);
map.get(a); // = 123
map.get(b); // = undefined


One simple workaround for this is to use strings or numbers as keys, as these are always considered equal when they have the same value:



const map: Map<string, number> = new Map<string, number>();

const a: [ number, number ] = [ 0, 0 ];
const b: [ number, number ] = [ 0, 0 ];

const astr: string = a.join(','); // = '0,0'
const bstr: string = b.join(','); // = '0,0'

// astr and bstr have the same value, and are strings so they are always equal
astr === bstr; // = true

map.set(astr, 123);
map.get(astr); // = 123
map.get(bstr); // = 123

[#58030] Friday, April 21, 2017, 7 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
travion

Total Points: 137
Total Questions: 96
Total Answers: 103

Location: India
Member since Wed, Aug 4, 2021
3 Years ago
travion questions
Mon, Dec 16, 19, 00:00, 5 Years ago
Sat, Oct 19, 19, 00:00, 5 Years ago
Fri, Sep 20, 19, 00:00, 5 Years ago
Wed, Nov 14, 18, 00:00, 6 Years ago
Sun, Oct 28, 18, 00:00, 6 Years ago
;