2017-04-24 19 views
4

在我的代码中点击这个奇怪的错误,我无法想象使用元组作为我的键时从Map中获得恒定时间查找的方式。Typescript/Javascript:使用元组作为映射的键

希望这说明了问题,我现在使用的解决办法只是为了得到它的工作:我使用

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

编译:

hello.ts(transpile?) :

tsc hello.ts -target es6 

TSC版本2.1.6

试了几件事情,使Map.get()我要努力工作,没有太大的成功。

回答

7

在JavaScript(以及作为扩展名的TypeScript)中,没有两个数组是相同的,除非它们指向相同的数组(即,更改一个元素也会改变另一个元素)。如果您创建一个具有相同元素的新数组,它不会认为它与现有的数组相同。

由于查找元素时,地图考虑这样的平等,如果你存储的值与数组作为键,你可以,如果你在完全相同的数组引用的一个关键传球再次只得到价值了一次:

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 

这样做的一个简单的解决方法是,当他们具有相同的值使用字符串或数字作为键,因为在这些视为相等:

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 
+0

非常有意义。谢谢! – ZackDeRose

2

我会创造我自己的类要做到这一点,使我可以很容易地使用所有的地图方法:

class MyMap { 
    private map = new Map<string, number>(); 

    set(key: [number, number], value: number): this { 
     this.map.set(JSON.stringify(key), value); 
     return this; 
    } 

    get(key: [number, number]): number | undefined { 
     return this.map.get(JSON.stringify(key)); 
    } 

    clear() { 
     this.map.clear(); 
    } 

    delete(key: [number, number]): boolean { 
     return this.map.delete(JSON.stringify(key)); 
    } 

    has(key: [number, number]): boolean { 
     return this.map.has(JSON.stringify(key)); 
    } 

    get size() { 
     return this.map.size; 
    } 

    forEach(callbackfn: (value: number, key: [number, number], map: Map<[number, number], number>) => void, thisArg?: any): void { 
     this.map.forEach((value, key) => { 
      callbackfn.call(thisArg, value, JSON.parse(key), this); 
     }); 
    } 
} 

code in playground

正如你所看到的,forEach例如会自动给你的密钥[number, number],而不是一个字符串,然后你会需要解析。

用例:

let map = new MyMap(); 
map.set([1, 2], 4); 
console.log(map.get([1, 2])) // 4 

map.set([3, 4], 20); 
map.forEach((v, k) => console.log(k, v)); 
// prints: 
// [1, 2] 4 
// [3, 4] 20 
+0

还有http://www.collectionsjs.com/,您可以使用它重写contentEquals和contentHash方法以确定关键等价。 –