2010-08-23 18 views
20

क्या जावास्क्रिप्ट में डेटा संरचना या पैटर्न है जिसका उपयोग फास्ट लुकअप (कुंजी द्वारा, सहयोगी सरणी के साथ) और ऑर्डर लूपिंग दोनों के लिए किया जा सकता है?फास्ट लुकअप और ऑर्डर लूपिंग के लिए जावास्क्रिप्ट डेटा स्ट्रक्चर?

ठीक है, अब मैं अपने डेटा को स्टोर करने के लिए ऑब्जेक्ट अक्षर का उपयोग कर रहा हूं लेकिन मैंने अभी यह खुलासा किया है कि संपत्ति नामों पर लूपिंग करते समय क्रोम आदेश को बनाए रखता नहीं है।

जावास्क्रिप्ट में इसे हल करने का कोई आम तरीका है?

किसी भी संकेत के लिए धन्यवाद।

+2

ध्यान दें, जावास्क्रिप्ट एक देशी 'Map' अब जो पाशन आदेश दिया गया है। –

उत्तर

30

स्वयं डेटा संरचना बनाएं। ऑर्डर को उस सरणी में संग्रहीत करें जो संरचना के लिए आंतरिक है। एक नियमित वस्तु में कुंजी द्वारा मैप किए गए ऑब्जेक्ट्स को स्टोर करें। आइए इसे OrderedMap पर कॉल करें जिसमें एक नक्शा, एक सरणी और चार मूलभूत विधियां होंगी।

OrderedMap 
    map 
    _array 

    set(key, value) 
    get(key) 
    remove(key) 
    forEach(fn) 

function OrderedMap() { 
    this.map = {}; 
    this._array = []; 
} 

कोई तत्व डालने पर, वांछित स्थिति के साथ-साथ ऑब्जेक्ट में सरणी में जोड़ें। इंडेक्स या अंत में सम्मिलन ओ (1) में है।

OrderedMap.prototype.set = function(key, value) { 
    // key already exists, replace value 
    if(key in this.map) { 
     this.map[key] = value; 
    } 
    // insert new key and value 
    else { 
     this._array.push(key); 
     this.map[key] = value; 
    } 
}; 

किसी ऑब्जेक्ट को हटाने पर, इसे सरणी और ऑब्जेक्ट से हटा दें। यदि किसी कुंजी या मूल्य से हटाना, जटिलता ओ (एन) है क्योंकि आपको ऑर्डर करने के लिए आंतरिक सरणी को पार करने की आवश्यकता होगी। इंडेक्स द्वारा हटाए जाने पर, जटिलता ओ (1) है क्योंकि आपके पास सरणी और ऑब्जेक्ट दोनों में मान तक सीधे पहुंच है।

OrderedMap.prototype.remove = function(key) { 
    var index = this._array.indexOf(key); 
    if(index == -1) { 
     throw new Error('key does not exist'); 
    } 
    this._array.splice(index, 1); 
    delete this.map[key]; 
}; 

लुकअप ओ (1) में होगा। एसोसिएटिव सरणी (ऑब्जेक्ट) से कुंजी द्वारा मान पुनर्प्राप्त करें।

OrderedMap.prototype.get = function(key) { 
    return this.map[key]; 
}; 

ट्रैवर्सल का आदेश दिया जाएगा और दृष्टिकोणों का उपयोग कर सकते हैं। जब ट्रैवर्सल का आदेश दिया जाता है, तो वस्तुओं के साथ एक सरणी बनाएं (केवल मान) और इसे वापस कर दें। एक सरणी होने के नाते, यह कुंजी की पहुंच का समर्थन नहीं करेगा। दूसरा विकल्प क्लाइंट से कॉलबैक फ़ंक्शन प्रदान करने के लिए कहना है जिसे सरणी में प्रत्येक ऑब्जेक्ट पर लागू किया जाना चाहिए।

OrderedMap.prototype.forEach = function(f) { 
    var key, value; 
    for(var i = 0; i < this._array.length; i++) { 
     key = this._array[i]; 
     value = this.map[key]; 
     f(key, value); 
    } 
}; 

इस तरह के एक वर्ग के लिए दस्तावेज और स्रोत के लिए बंद लाइब्रेरी के किसी LinkedMap की Google के क्रियान्वयन देखें।

+0

ग्रेट उत्तर, धन्यवाद। – Haes

+0

लुकअप ओ (1) कैसे हैं? यदि आप किसी सरणी इंडेक्स के अलावा कुछ भी उपयोग कर रहे हैं, तो जेएस प्रॉपर्टी रेज़ोल्यूशन ओ (एन) है (इसे प्रोटोटाइप श्रृंखला के माध्यम से लूप करके हल करना है) http://bonsaiden.github.io/JavaScript-Garden/ – ginman

+4

पर संपत्ति लुकअप देखें तथ्य यह है कि इसे प्रोटोटाइप श्रृंखला को पार करना है, फिर भी यह ओ (एन) नहीं बनाता है। एक प्रोटोटाइप श्रृंखला पदानुक्रम 4 स्तरों की गहराई की कल्पना करें और प्रत्येक स्तर कुंजी और मूल्यों को पकड़ने के लिए हैश संरचना को बनाए रखता है। फिर इसे केवल औसतन 4, ओ (1) लुकअप की आवश्यकता होगी। यह अभी भी ओ (1) है। अब तक, जहां तक ​​मुझे पता है, ईसीएमएस्क्रिप्ट कार्यान्वयन विवरण जरूरी नहीं है, इसलिए यदि कोई चाहें तो कोई इसे ओ (एन²) में कर सकता है। दूसरे शब्दों में, यह कार्यान्वयन निर्भर है, लेकिन सबसे सभ्य कार्यान्वयन दिए जाने पर, आप औसत पर ओ (1) लुकअप की अपेक्षा कर सकते हैं। – Anurag

3

एकमात्र उदाहरण जिसमें क्रोम किसी ऑब्जेक्ट में चाबियों के क्रम को बनाए रखता है, ऐसा लगता है कि कुंजी संख्यात्मक हैं।

var properties = ["damsonplum", "9", "banana", "1", "apple", "cherry", "342"]; 
    var objLiteral = { 
    damsonplum: new Date(), 
    "9": "nine", 
    banana: [1,2,3], 
    "1": "one", 
    apple: /.*/, 
    cherry: {a: 3, b: true}, 
    "342": "three hundred forty-two" 
    } 
    function load() { 
    var literalKeyOrder = []; 
    for (var key in objLiteral) { 
     literalKeyOrder.push(key); 
    } 

    var incremental = {}; 
    for (var i = 0, prop; prop = properties[i]; i++) { 
     incremental[prop] = objLiteral[prop]; 
    } 

    var incrementalKeyOrder = []; 
    for (var key in incremental) { 
     incrementalKeyOrder.push(key); 
    } 
    alert("Expected order: " + properties.join() + 
      "\nKey order (literal): " + literalKeyOrder.join() + 
      "\nKey order (incremental): " + incrementalKeyOrder.join()); 
    } 

क्रोम में, ऊपर का उत्पादन: "1,9,342, damsonplum, केला, सेब, चेरी"।

अन्य ब्राउज़रों में, यह "Damsonplum, 9, केले, 1, सेब, चेरी, 342" पैदा करता है।

तो जब तक कि आपकी चाबियाँ संख्यात्मक न हों, मुझे लगता है कि क्रोम में भी, आप सुरक्षित हैं। और यदि आपकी चाबियां संख्यात्मक हैं, तो शायद उन्हें एक स्ट्रिंग के साथ प्रीपेड करें।

+1

क्या यह सामान्य रूप से V8 पर लागू होता है, इसलिए Node.js पर भी? –

2

has been noted रूप में, यदि अपनी चाबी सांख्यिक हैं आप को बचाने के लिये एक तार के साथ उन्हें पहले जोड़ें कर सकते हैं।

var qy = { 
    _141: '256k AAC', 
    _22: '720p H.264 192k AAC', 
    _84: '720p 3D 192k AAC', 
    _140: '128k AAC' 
}; 

Example

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