2017-04-24 20 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方法以確定關鍵等價。 –