2010-07-22 14 views
10

जावास्क्रिप्ट, सभी वस्तुओं HashMaps की तरह एक सा काम करते हैं। हालांकि, इन हैशैप्स की चाबियाँ तार होनी चाहिए। वे नहीं कर रहे हैं, वे toString() साथ परिवर्तित कर रहे हैं। इसका मतलब है कि:क्या जावास्क्रिप्ट के लिए हैशपैप लाइब्रेरी है?

var a = {foo: 1}; 
var b = {bar: 2}; 
var o = {}; 
o[a] = 100; 
o[b];    // 100 
JSON.stringify(o); // '{"[object Object]":100}' 

यही है, के बाद से किसी भी सादे वस्तु की toString()[object Object] है, वे सभी एक ही मूल्य का समाधान करें।

मैं एक hashmap जहां एक ही गुणों के साथ ऑब्जेक्ट्स और मूल्यों एक ही मूल्य का पता है, लेकिन विभिन्न गुणों या मूल्यों विभिन्न मूल्यों को संबोधित के साथ वस्तुओं को बनाने के लिए करना चाहते हैं। यही कारण है:

var a = {foo: 1}; 
var b = {bar: 2, baz: 3}; 
var c = {baz: 3, bar: 2}; 
var hash = new Hash(); 
hash.set(a, 100); 
hash.get(b);  // undefined 
hash.set(b, 200); 
hash.get(b);  // 200 
hash.get(c);  // 200 

मेरी पहली वृत्ति तार में वस्तुओं चालू करने के लिए JSON.stringify() उपयोग करने के लिए गया था, लेकिन:

var hash = {}; 
var b = {bar: 2, baz: 3}; 
var c = {baz: 3, bar: 2}; 
hash[JSON.stringify(b)] = 100 
hash[JSON.stringify(b)] // 100 
hash[JSON.stringify(c)] // undefined 
JSON.stringify(b)  // '{"bar":2,"baz":3}' 
JSON.stringify(c)  // '{"baz":3,"bar":2}' 

है, JSON क्रमबद्धता क्रम पर निर्भर है।

वहाँ एक अच्छा पुस्तकालय या तकनीक इस तरह एक hashmap लागू करने के लिए है?

अद्यतन:

hash({foo: 1, bar: 2}) == hash({bar: 2, foo: 1}) 

उत्तर

2

यहां एक त्वरित सबूत अवधारणा-का-मैं शायद ही यह बिल्कुल परीक्षण किया है है ...

, और मुझे विश्वास है कि वहाँ कोने-मामलों है कि इसके साथ सौदा नहीं कर सकते हो जाएगा हूँ।

प्रदर्शन बेहद अक्षम होगा क्योंकि __createHash फ़ंक्शन किसी भी ऑब्जेक्ट के सदस्यों के माध्यम से पुन: कार्य करने की आवश्यकता है और फिर उन्हें "हैश" उत्पन्न करने के लिए क्रमबद्ध करने की आवश्यकता है जो आपकी आवश्यकताओं को पूरा करता है।

HashMap = function() { 
    this.get = function(key) { 
     var hash = this.__createHash(key); 
     return this.__map[hash]; 
    }; 

    this.set = function(key, value) { 
     var hash = this.__createHash(key); 
     this.__map[hash] = value; 
    }; 

    this.__createHash = function(key) { 
     switch (typeof key) { 
      case 'function': 
       return 'function'; 

      case 'undefined': 
       return 'undefined'; 

      case 'string': 
       return '"' + key.replace('"', '""') + '"'; 

      case 'object': 
       if (!key) { 
        return 'null'; 
       } 

       switch (Object.prototype.toString.apply(key)) { 
        case '[object Array]': 
         var elements = []; 
         for (var i = 0; i < key.length; i++) { 
          elements.push(this.__createHash(key[i])); 
         } 
         return '[' + elements.join(',') + ']'; 

        case '[object Date]': 
         return '#' + key.getUTCFullYear().toString() 
            + (key.getUTCMonth() + 1).toString() 
            + key.getUTCDate().toString() 
            + key.getUTCHours().toString() 
            + key.getUTCMinutes().toString() 
            + key.getUTCSeconds().toString() + '#'; 

        default: 
         var members = []; 
         for (var m in key) { 
          members.push(m + '=' + this.__createHash(key[m])); 
         } 
         members.sort(); 
         return '{' + members.join(',') + '}'; 
       } 

      default: 
       return key.toString(); 
     } 
    }; 

    this.__map = {}; 
} 
+0

हाँ, इसे कुछ काम करने की ज़रूरत है जो कि परफॉर्मेंट और बुलेट प्रूफ हो, लेकिन मुझे लगता है कि आपको सही विचार मिल गया है। – Peeja

+0

@Pij: मुझे यकीन नहीं है कि यह अभी भी आपकी आवश्यकताओं को पूरा करते हुए प्रदर्शन किया जा सकता है। हालांकि, आपकी सटीक जरूरतों के आधार पर शायद इसे काफी अच्छा बनाया जा सकता है। – LukeH

0

आप एक toString कि चाबियों का एक आदेश सुनिश्चित करता है के साथ अपने स्वयं वर्ग को लागू कर सकते हैं:

तुल्य, वहाँ एक अच्छा हैशिंग समारोह ऐसा है कि है।

+0

वही है जो मैं करने की कोशिश कर रहा हूं। – Peeja

0

प्रोटोटाइप हैश काफी अच्छी तरह से http://prototypejs.org/api/hash

+1

प्रोटोटाइप का 'हैश' कार्यान्वयन एक मनमानी वस्तु को कुंजी के रूप में संग्रहीत करने के लिए काम नहीं करेगा, ओपी के पास अभी भी वही परिणाम होंगे जो अब हो रहे हैं, ['set' विधि] (http: // github) के कार्यान्वयन की जांच करें। कॉम/स्स्टेफेसन/प्रोटोटाइप/ब्लॉब/मास्टर/src/lang/हैश.जेएस # एल 124) और [यह उदाहरण] (http://jsbin.com/imeqa3/edit)। – CMS

8

कवर मैं Tim Down से आप jshashtable परियोजना की सिफारिश करेंगे है।

+1

jshashtable एक अच्छी शुरुआत है, लेकिन यह केवल तभी काम करता है जब कुंजी एक ही वस्तु है। मैं ऊपर दिए गए कोड में एक अलग लेकिन समान वस्तु ('बी' बनाम 'सी' का उपयोग करने में सक्षम होना चाहता हूं)। अनिवार्य रूप से, मुझे एक पुस्तकालय की आवश्यकता है जो गुणों और मूल्यों के समानता की अच्छी परिभाषा प्रदान करता है। – Peeja

+1

जैसा कि मैं :) इस मामले में, आपको एक कस्टम 'बराबर' फ़ंक्शन की आवश्यकता होगी जो दो ऑब्जेक्ट्स की गुणों की तुलना करता है, या तो आपकी ऑब्जेक्ट्स की विधि के रूप में या बेहतर, 'हैशटेबल' कन्स्ट्रक्टर में पारित किया गया: 'var itemsEqual = function (o1, o2) {के लिए (var i में o1) {if (o1 [i]! == o2 [i]) {झूठी वापसी; }} के लिए (मैं ओ 2 में) {अगर (! (मैं ओ 1 में)) {झूठी वापसी; }} सच वापसी; }; var हैश = नया हैशटेबल (शून्य, ऑब्जेक्ट एक्वाल); ' –

+0

पिज्जा: jshashtable उस मामले को संभालता है जब आप इसे अपने स्वयं के समानता समारोह के साथ प्रदान करते हैं, जैसा कि मेरी टिप्पणी में है (फ़ॉर्मेटिंग की कमी को क्षमा करें; टिप्पणियां किसी भी बेहतर अनुमति नहीं देती हैं)। –

0

jOrder जब एक सूचकांक लुकअप एक ही गुण (लेकिन अलग अलग क्रम में) समान रूप के साथ वस्तुओं के इलाज के लिए संशोधित किया जा सकता है।

आप अपनी सूची में वस्तु {bar: 2, baz: 3, val: 200} है, और आप पहले से इस तरह की एक jOrder मेज पर एक फिटिंग सूचकांक डाल गया है:

var table = jOrder(data) 
    .index('signature', ['bar', 'baz'], {grouped: true}); 

तो अभी table.where([{bar: 2, baz: 3}])[0].val 200 वापस आ जाएगी, लेकिन table.where([{baz: 3, bar: 2}])[0].val नहीं होगा । यह बहुत प्रयास हालांकि नहीं ले यह गुण के आदेश पर निर्भर नहीं बनाना चाहते हैं। यदि आप रुचि रखते हैं तो मुझे बताएं और मैं जितनी जल्दी हो सके गिटहब को फिक्स को दबा दूंगा।

+0

एफवाईआई मैंने परिवर्तन जमा किया। ऊपर दिए गए प्रश्न अब 200 लौटाएंगे। –

-2

उत्तर दो सरणी का उपयोग करना है, एक कुंजी के लिए, एक मूल्यों के लिए।

var i = keys.indexOf(key) 
if (i == -1) 
    {keys.push(key); values.push(value)} 
else 
    {values[i] = value; } 
+0

मुझे यकीन नहीं है कि मैं समझता हूं। यह कोड क्या करना है? – Peeja

+0

कृपया मत करो। आपके पास एक प्रदर्शन दुःस्वप्न होगा। बेंचमार्क यहां: http://people.iola.dk/arj/2012/05/30/hashtables-in-javascript/ –

+0

यह मूल प्रश्न का उत्तर नहीं देता है, जो ऑब्जेक्ट कुंजी के साथ हैशैप्स बनाने के बारे में है। – FoolishSeth

0

इस धागे ने मुझे वास्तव में मेरे वर्तमान प्रोजेक्ट में एक बग खोजने का नेतृत्व किया। हालांकि, यह अब तय है और मेरे प्रोजेक्ट में मेरे हैश मैप कार्यान्वयन (https://github.com/Airblader/jsava) ठीक वही करेंगे जो आपने वर्णित किया था। Jshashtable के विपरीत, कोई बाल्टी नहीं हैं।

2

यह एक पुरानी सवाल है, लेकिन ES6 एक विशेषता यह है कि प्रासंगिक हो सकती है: Map

मैप्स मूल्यों के रूप में कुंजी के रूप में मनमाने ढंग से वस्तुओं, और मनमाने ढंग से मान हो सकते हैं। मुख्य भेद यह है कि कुंजी के रूप में उपयोग की जाने वाली वस्तुएं अद्वितीय रहती हैं, भले ही ऑब्जेक्ट समान हों।

var map = new WeakMap(); 

var o1 = {x: 1}; 
var o2 = {x: 1}; 

map.set(o1, 'first object'); 
map.set(o2, 'second object'); 

// The keys are unique despite the objects being identical. 

map.get(o1); // 'first object' 
map.get(o2); // 'second object' 
map.get({x: 1}); // undefined 

JSON.stringify वस्तुओं ing नहीं o1 और o2 के बीच अंतर करने में सक्षम हो जाएगा:

यहाँ एक उदाहरण है।

एमडीएन में more info है। WeakMap भी है जो कुंजी के रूप में उपयोग की जाने वाली वस्तुओं के संदर्भों को बनाए रखता नहीं है, इसलिए वे कचरा एकत्र हो सकते हैं।

Traceur compiler में अभी तक मानचित्र और वीकमैप के लिए आधिकारिक पॉलीफिल नहीं हैं, लेकिन दोनों के लिए पॉलीफिल के साथ एक खुला पुल अनुरोध है। उन पॉलीफिल के लिए कोड (यदि कोई उन्हें व्यक्तिगत रूप से जोड़ना चाहता है) यहां हैं: Map और WeakMap। मान लें कि उन पॉलीफिल अच्छी तरह से काम करते हैं, आप आज मानचित्र या वीकैप का उपयोग शुरू कर सकते हैं। :)

संबंधित मुद्दे