2017-07-06 58 views
2

查看幾個不同的文檔,我看到的全部是當Map(ECMAScript6)鍵是布爾值,字符串或整數時。有沒有辦法我們可以使用另一個自定義對象(用新的CustomObject(x,y)構造函數調用調用)添加爲關鍵字?如何檢查Javascript Map是否有對象鍵

我能夠添加一個對象作爲一個鍵,但無法檢查如果地圖具有上述對象。

var myMap = new Map(); 
myMap.set(new Tuple(1,1), "foo"); 
myMap.set('bar', "foo"); 


myMap.has(?); 
myMap.has('bar'); // returns true 

有沒有辦法解決這個問題?

var myMap = new Map(); 
    myMap.set(new Tuple(1,1), "foo"); 

for(some conditions) { 
var localData = new Tuple(1,1); //Use directly if exists in myMap? 
map.has(localData) // returns false as this is a different Tuple object. But I need it to return true 
} 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has

+0

是的,你可以使用任何對象作爲一個關鍵。它必須每次都是同一個對象 - 不僅僅是一個具有相同鍵和值的對象。嵌套的'Map'是實現'Tuple'查找的一個選項。 – Ryan

+0

不幸的是我不能檢查它是否是同一個對象本身。它必須是具有相同設置的一些共同屬性的對象。有沒有辦法做到這一點? –

回答

3

你只需要保存參考對象:

var myMap = new Map(); 
var myKey = new Tuple(1,1); 
myMap.set(myKey, "foo"); 
myMap.set('bar', "foo"); 

myMap.has(myKey);   // returns true; myKey === myKey 
myMap.has(new Tuple(1,1)); // returns false; new Tuple(1,1) !== myKey 
myMap.has('bar');   // returns true; 'bar' === 'bar' 

編輯:這裏是如何使用對象來實現你想要的東西,這是比較對象通過它們的值而不是參考:

function Tuple (x, y) { 
    this.x = x; 
    this.y = y; 
} 
Tuple.prototype.toString = function() { 
    return 'Tuple [' + this.x + ',' + this.y + ']'; 
}; 

var myObject = {}; 
myObject[new Tuple(1, 1)] = 'foo'; 
myObject[new Tuple(1, 2)] = 'bar'; 
console.log(myObject[new Tuple(1, 1)]); // 'foo' 
console.log(myObject[new Tuple(1, 2)]); // 'bar' 

這些操作將ru n在平均時間內保持不變,這比在線性時間內通過Map查找類似的對象密鑰要快得多。

+0

謝謝。不幸的是,我不能使用與對象相同的myKey引用。我正在檢查一組具有相同屬性的對象。有什麼辦法可以解決這個問題嗎? –

+0

@LoserCoder是的,爲您的類創建一個toString()方法,爲具有相同值的實例生成相同的字符串,然後將這些字符串用作對象中的鍵(這樣您甚至不必使用Map) 。這就是地圖和對象比較在JS中的工作原理 - 通過引用比較對象。 – sbking

+0

@LoserCoder我加了一個我的意思的例子。這種方法讓你確保你的toString方法能夠準確地序列化你的值對象進行比較。僅僅因爲兩個對象是用相同的構造函數和參數創建的,並不意味着它們必然是等價的。 – sbking

1

當您將對象設置爲地圖時,您需要在檢查地圖是否存在時傳遞相同的內存引用。

例子:

const map = new Map(); 

map.set(new Tuple(1,1)); 
map.has(new Tuple(1,1)) // False. You are checking a new object, not the same as the one you set. 

const myObject = new Tuple(1,1); 
map.set(myObject); 
map.has(myObject) // True. You are checking the same object. 

編輯

如果你真的要做到這一點,你可以做到以下幾點:

function checkSameObjKey(map, key) { 
    const keys = map.keys(); 
    let anotherKey; 

    while(anotherKey = keys.next().value) { 
     // YOUR COMPARISON HERE 
     if (key.id == anotherKey.id) return true; 
    } 

    return false; 
} 

const map = new Map(); 
map.set({id: 1}, 1); 

checkSameObjKey(map, {id: 1}); // True 
checkSameObjKey(map, {id: 2}); // False 
+0

是的,但我在尋找是否有已知的解決方法。或者應該在這種情況下不使用Set/Map。如果是這樣,我可能不得不直接使用對象引用,但這會導致相同的問題。 –

+0

用可能的解決方法編輯我的答案。 @LoserCoder – tiagodws

+0

請注意,此方法使用線性查找,運行速度比使用JavaScript引擎的內置對象密鑰解析算法(散列表)(其平均時間恆定)運行速度要慢很多。 – sbking

相關問題