2012-01-13 18 views
15

मुझे ऑब्जेक्ट्स वाले जावास्क्रिप्ट सरणी को खोजने की आवश्यकता होती है। मैं उस सरणी में किसी ऑब्जेक्ट को खोजना चाहता हूं जिसमें एक संपत्ति मैच है। उदाहरण के लिए, व्यक्ति की आईडी/कुंजी === "एबीसी 123"क्या jQuery के प्रत्येक का उपयोग करने से जावास्क्रिप्ट ऐरे खोजने का कोई बेहतर तरीका है?

यह $ .each विधि का उपयोग करके jQuery का उपयोग करके बहुत आसानी से किया जा सकता है, जो मैंने तय किया है। आप jsFiddle में उदाहरण यहां देख सकते हैं। http://jsfiddle.net/johnpapa/EJAFG/

मुझे आश्चर्य है कि किसी और को ऐसा करने के लिए तेज़ और/या बेहतर तरीका मिला है?

var Person = function(code, name) { 
    this.code = code; 
    this.name = name; 
}; 
var people = [ 
    new Person("ABC123", "Tooth Fairy"), 
    new Person("DEF456", "Santa Claus"), 
    new Person("PIR000", "Jack Sparrow"), 
    new Person("XYZ987", "Easter Bunny") 
    ]; 

var utils = {}; 
// Could create a utility function to do this 
utils.inArray = function(searchFor, property) { 
    var retVal = -1; 
    $.each(this, function(index, item) { 
     if (item.hasOwnProperty(property)) { 
      if (item[property].toLowerCase() === searchFor.toLowerCase()) { 
       retVal = index; 
       return false; 
      } 
     } 
    }); 
    return retVal; 
}; 

// or we could create a function on the Array prototype indirectly 
Array.prototype.inArray = utils.inArray; 

// let's use the prototype for now 
var i = people.inArray("PIR000", "code"); 
$('#output').text(people[i].name); 

बहुत चलो इस एक के लिए इसी तरह के सवाल के होते हैं, लेकिन मैं अभी तक पुनरावृत्ति के अलावा किसी अन्य समाधान के साथ एक को देखने के लिए (जैसे मैं यहाँ किया था) है।

तो सवाल यह है कि ... क्या कोई बेहतर तरीका है?

+0

एक समान प्रश्न है [यहां] [1]। [1]: http://stackoverflow.com/questions/1144423/jquery-selectors-for-plain-javascript-objects-instead-of-dom-elements –

+0

http://stackoverflow.com देखें/प्रश्न/143847/सर्वोत्तम-तरीके-से-खोजने-एक-आइटम-इन-ए-जावास्क्रिप्ट-सरणी और http://stackoverflow.com/questions/237104/array-containsobj-in-javascript – j08691

+0

@ j08691 उन दोनों जांच कर रहे हैं कि कोई सटीक ऑब्जेक्ट मैच मौजूद है या नहीं। उन लोगों के लिए, $ .inArray ठीक काम करता है। मैं कुंजी द्वारा एक खोज की तलाश में हूँ। –

उत्तर

16

$। हम ओ (एन) के बारे में सोचेंगे। किसी भी साधारण "फॉर" लूप जो किसी लागू आइटम को तोड़ने पर टूट जाता है, वह अधिकतर ओ (एन) पर होगा, लेकिन औसत पर तब तक कम होगा जब तक कि सरणी के बाद वाले आइटम लगातार मेल खाने वाले तत्व नहीं पाए जाते। Array.filter एक तरीका है जो काम करता है लेकिन कुछ ब्राउज़रों के लिए मूल नहीं है। यदि आप इसका उपयोग करना चाहते हैं तो Array.filter विधि के शुद्ध जावास्क्रिप्ट कार्यान्वयन हैं। उन ब्राउज़रों के लिए जो इसे मूल रूप से होस्ट करते हैं, यह शायद तेज़ी से निष्पादित होगा क्योंकि उनके कार्यान्वयन को शायद संकलित किया गया है और मूल कोड में भाग लिया गया है। लेकिन फ़िल्टर विधि हमेशा ओ (एन) उत्पन्न करती है क्योंकि यह सरणी के तत्वों को एक नई सरणी में "फ़िल्टर" करती है।

मैं व्यक्तिगत रूप से (int i = 0; ...) दृष्टिकोण के साथ चिपकता हूं। अन्य कार्यों को कॉल करके गुंजाइश के कम ओवरहेड को बदलना और आप मिलान किए गए तत्व पर आसानी से "ब्रेक" कर सकते हैं।

मैं यह भी जोड़ना चाहता था कि आप एचटीएमएल 5 द्वारा प्रदान किए गए स्थानीय डेटाबेस स्टोरेज (जो एसक्लाइट का उपयोग करते हैं) का उपयोग कर सकते हैं। यह स्पष्ट रूप से व्यापक रूप से समर्थित नहीं है लेकिन डेटा के बड़े सेट के बाद किसी अन्य जावास्क्रिप्ट दृष्टिकोण से बहुत तेज़ होगा।

http://blog.darkcrimson.com/2010/05/local-databases/

यहाँ कुछ हद तक एक बंद कर की दीवार तरीका है:: यहाँ एक लिंक आप इसे बाहर की जाँच करना चाहते हैं है आप अपने डेटा सैद्धांतिक रूप से सूचकांक और यह एक तेजी से में उन लोगों के indicies का उपयोग कर पुनः प्राप्त कर सकता है तौर तरीका। जावास्क्रिप्ट सरणी में अपना डेटा संग्रहीत करने के बजाय, आप इसे "डेटा-आईडी -5" जैसे सीएसएस वर्गों का उपयोग करके तत्वों को डीओएम और "इंडेक्स" में संग्रहीत करते हैं। यह आपको अधिकांश प्रमुख ब्राउज़रों में निर्मित देशी चयनकर्ता API का उपयोग करने का लाभ देता है। यहाँ एक उदाहरण है:

डोम:

<div id="datastuff" style="display:none"> 
    <span class="data-id-ABC123" data-person='{"code": "ABC123", "name": "Tooth Fairy"}'></span> 
    <span class="data-id-DEF456" data-person='{"code": "DEF456", "name": "Santa Claus"}'></span> 
    <span class="data-id-PIR000" data-person='{"code": "PIR000", "name": "Jack Sparrow"}'></span> 
    <span class="data-id-XYZ987" data-person='{"code": "XYZ987", "name": "Easter Bunny"}'></span> 
</div> 

अब हम इसके लिए jQuery और क्वेरी का उपयोग कर सकते हैं: हो सकता है कि

var person = $(".data-id-ABC123").data("person"); 
console.log(person.name);//Tooth Fairy 
+0

+1। लूप के लिए एक सरल संभवतः क्लीनर (बाहरी पुस्तकालय पर निर्भरता नहीं) और तेज़ (कम फ़ंक्शन कॉल, कोई jQuery ऑब्जेक्ट सृजन) नहीं है, लेकिन ओपी का मानदंड भिन्न हो सकता है। यदि यह एक ऑपरेशन है जो अक्सर एक बड़े सरणी पर किया जाता है, तो एक साधारण इंडेक्स एक नई वस्तु जोड़ने पर एक छोटा ओवरहेड होता है जो खोज करते समय प्रदर्शन में काफी वृद्धि कर सकता है। इनपुट के लिए – RobG

+0

+1 @odie धन्यवाद। मुझे लूप या $ के लिए सोचने के लिए प्रेरित करता है। प्रत्येक ठीक है। इसकी एक खोज है, इसलिए जादू बुलेट नहीं है। विचारों को उछालना सिर्फ अच्छा है :) –

+1

मैंने एक और तरीका जोड़ा है, बिना संदेह के, अविश्वसनीय रूप से तेज़ और तकनीकी रूप से कोई लूप के साथ सीधे नहीं होगा। आईडी का उपयोग करने के लिए इंडेक्स को बदलें और आप केवल एलीमेंटबीआईआईडी ("डेटा-आईडी-एबीसी 123") प्राप्त कर सकते हैं जो आजकल अधिकांश ब्राउज़रों में लगभग एक कठिन प्रक्रिया है। – doogle

0

आप कर सकते हैं: हम "ABC123" के प्रमुख के लिए क्वेरी करेंगे इसे for..in के साथ लूप करें। देखें: http://www.w3schools.com/js/js_loop_for_in.asp। Php के foreach के रूप में एक similair फैशन में काम करता है।

+1

मैं "मानता हूं" के लिए/in $ .each जैसा ही प्रदर्शन है ... लेकिन शायद मैं गलत हूं। प्रयास योग्य। –

+0

फॉर-इन * नहीं * एक foreach है। * नहीं * इसे सरणी पर फिर से चलाने के लिए उपयोग करें। इसके अलावा, [http://w3fools.org) w3schools – hugomg

+0

पर नहीं कहा था कि वे वही थे, लेकिन इसका उपयोग किसी सरणी को फिर से करने के लिए क्यों नहीं करते? Www.w3fools.com के बारे में हेड-अप के लिए धन्यवाद। साइट और पढ़ने के बाद निश्चित रूप से आपका और उनका बिंदु मान्य है। – Ruben

6

यह आपके "खोज" प्रश्न का उत्तर नहीं देता है, लेकिन यह आपके लिए एक समाधान हो सकता है। आप एक विशेष PersonArray कक्षा बना सकते हैं जो इसके भीतर के लोगों को अनुक्रमणित करता है। इस दृष्टिकोण के साथ प्रदर्शन ओ (1) है, लेकिन यह अधिक स्मृति का उपयोग करता है।

var PersonArray = function(persons) { 
    this.elements = {}; 
    var i; 
    for (i=0; i < persons.length; i++) { 
     this.elements[persons[i].code] = persons[i]; 
    } 
}; 

PersonArray.prototype.fromCode = function(s) { 
    return this.elements[s]; 
}; 

var people = new PersonArray([ 
    new Person("ABC123", "Tooth Fairy"), 
    new Person("DEF456", "Santa Claus"), 
    new Person("PIR000", "Jack Sparrow"), 
    new Person("XYZ987", "Easter Bunny") 
    ]); 

console.log(people.fromCode("ABC123")); // Prints a person 
console.log(people.fromCode("DEF456")); // Prints a person 
console.log(people.fromCode("NONE")); // Undefined 

आप इस क्षेत्र को अन्य क्षेत्रों को इंडेक्स करने के लिए भी बढ़ा सकते हैं।

यह भी देखें: a demo और a benchmark (100,000 तत्वों के साथ)।

7

सामान्य रूप से आप सरणी से तत्वों को तेज़ी से नहीं प्राप्त कर सकते हैं तब ओ (एन) जब तक कि आप जो कुछ भी इंडेक्स करना चाहते हैं उसके बारे में कुछ नहीं जानते।

उदाहरण के लिए, यदि आप तुलनात्मक रूप से अनुक्रमणित कर रहे हैं जो तुलनीय है तो आप सरणी को सॉर्ट कर सकते हैं और बाइनरी खोज कर सकते हैं।

यदि आप कॉलम पर खोज कर रहे हैं और मान इनट्स या तार हैं तो आप सादा जावास्क्रिप्ट ऑब्जेक्ट्स हैश टेबल के रूप में उपयोग कर सकते हैं।

var people = [ 
    new Person("ABC123", "Tooth Fairy"), 
    new Person("DEF456", "Santa Claus"), 
    new Person("PIR000", "Jack Sparrow"), 
    new Person("XYZ987", "Easter Bunny") 
]; 

var people_table = {}; 
for(var i=0; i<people.length; i++){ 
    people_table[ people[i].id ] = people[i]; 
} 

//fast search: 
var someone = people_table['ABC123']; 

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

+0

कूल, लेकिन डुप्लिकेट से निपटना चाहिए। – RobG

+0

डुप्लीकेट को संभालना उन चीजों की तरह है जो हाथ से करने के लिए परेशान हो जाते हैं। उम्मीद है कि आप लीट पर हर किसी के लिए एक अद्वितीय आईडी दे सकते हैं। – hugomg

+0

कूल विचार। हैशिंग बहुत बढ़िया है यदि आपको पता है कि आप किस चीज से अनुक्रमित करेंगे। इस मामले में मैं इसका उपयोग नहीं कर सकता, मुझे यह पसंद है। –

1

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

यह ऑब्जेक्ट नामों की एक अनुक्रमणिका रखता है (यदि उनके पास एक है) ताकि उन्हें प्राप्त करना कुशल हो।

आप केवल बड़ी संख्या में ऑब्जेक्ट्स (100 से अधिक या उससे अधिक कहें) के लिए एक प्रदर्शन टक्कर देखेंगे और केवल इंडेक्स वाले लोगों के लिए (हालांकि आप किसी भी गुण के लिए इंडेक्स बना सकते हैं और एक हो सकता है ऐसा करने के लिए और अधिक सामान्य विधि)।

function Storage() { 
    this.store = []; 
    this.nameIndex = {}; 
} 

// Add item to the store, if has name property, add name to name index 
Storage.prototype.addItem = function(item) { 
    var idx = this.nameIndex; 

    // If the item has a name property 
    if (item.hasOwnProperty('name')) { 

    // If already have an item with that name, add index of 
    // this item to indexs of same named items 
    if (idx.hasOwnProperty(item.name)) { 
     idx[item.name].push(this.store.length); 

    // Otherwise, add this item to the index 
    } else { 
     idx[item.name] = [this.store.length]; 


    } 
    } 
    // Add the item to the store 
    this.store.push(item); 
} 

// Returns a possibly empty array of items with matching names 
Storage.prototype.getItemsByName = function(name) { 
    var result = []; 
    var names; 

    if (this.nameIndex.hasOwnProperty(name)) { 
    list = this.nameIndex[name]; 

     for (var i=0, iLen=list.length; i<iLen; i++) { 
     result.push(this.store[list[i]]); 
     } 
    } 
    return result; 
} 

// Generic method for any property and value 
Storage.prototype.getItemsByAttributeValue = function(propName, propValue) { 
    // loop through items, return array of 
    // those with matching property and value 
} 


var store = new Storage(); 

store.addItem({name:'fred',age:'9'}); 

var obj = store.getItemsByName('fred'); 

alert(obj[0].age); // 9 

store.addItem({name:'sally',age:'12'}); 

obj = store.getItemsByName('sally'); 

alert(obj[0].age); //12 
0

मैं बार-बार एक सरणी खोज करने के लिए है, तो मैं इसे एक बार पुनरावृति, जिसमें मैं एक वस्तु की एक संपत्ति के रूप में प्रत्येक कुंजी जोड़ें और फिर उस वस्तु में कुंजी ऊपर देखो। यह ओ (एन) + सी पर सभी लुकअप का लक्ष्य रखता है। संग्रहण कुशल है क्योंकि ऑब्जेक्ट सरणी डेटा के संदर्भ संग्रहीत कर रहा है, या वे primitives हैं। सरल और तेज़

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

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