2011-06-05 18 views
99

से अधिक सरणी तत्व की अनुक्रमणिका प्राप्त करें, मेरे पास एक विशाल सरणी है, और इससे एक मूल्य है। मैं सरणी में मान का सूचकांक प्राप्त करना चाहता हूं। क्या कोई अन्य तरीका है, इसके बजाय इसे पाने के लिए Array#index पर कॉल करें? समस्या वास्तव में विशाल सरणी रखने और Array#index पर भारी मात्रा में कॉल करने की आवश्यकता से आती है।ओ (एन)

की कोशिश करता की एक जोड़ी के बाद मैंने पाया कि कैशिंग मूल्य खुद के बजाय (value, index) क्षेत्रों के साथ structs भंडारण के द्वारा तत्वों के अंदर अनुक्रमित प्रदर्शन में एक बड़ा कदम (20x बार जीता) देता है।

फिर भी मुझे आश्चर्य है कि कैशिंग के बिना एन तत्व के सूचकांक को खोजने का एक और सुविधाजनक तरीका है (या एक अच्छी कैशिंग तकनीक है जो प्रदर्शन को बढ़ावा देगी)।

उत्तर

112

सरणी को हैश में कनवर्ट करें। फिर कुंजी की तलाश करें।

array = ['a', 'b', 'c'] 
hash = Hash[array.map.with_index.to_a] # => {"a"=>0, "b"=>1, "c"=>2} 
hash['b'] # => 1 
+2

सबसे तेज अगर सरणी बहुत लंबी है – Kevin

+16

आपके उपयोग के मामले के आधार पर यदि डुप्लिकेट मान हैं तो यह समस्याग्रस्त हो सकता है। ऊपर वर्णित विधि समकक्ष या # रेन्डेक्स (मूल्य की अंतिम घटना) # इंडेक्स समकक्ष परिणाम प्राप्त करने के लिए, अर्थ है कि हैश ने मूल्य की पहली अनुक्रमणिका को वापस करने के लिए आपको रिवर्सिंग के साथ कुछ करने की आवश्यकता होगी हैश बनाने से पहले सरणी, फिर प्रारंभिक सरणी की कुल लंबाई से लौटाए गए इंडेक्स मूल्य को घटाना - 1. # (array.length - 1) - हैश ['बी'] – ashoda

+1

क्या हैश में रूपांतरण नहीं है समय पर? मुझे लगता है कि अगर इसे एक से अधिक बार इस्तेमाल किया जा रहा है, तो हैश रूपांतरण अधिक प्रदर्शनशील होगा। लेकिन एकल उपयोग के लिए, क्या यह सरणी के माध्यम से फिर से अलग नहीं है? – ahnbizcad

6

क्या हैश का उपयोग न करने का कोई अच्छा कारण है? सरणी के लिए लुकअप O(1) बनाम O(n) हैं।

+0

बिंदु है करने के लिए - मैं हैश है, जो एक सरणी मैं उपयोग कर रहा हूँ रिटर्न पर फोन कर रहा हूँ '# keys'। फिर भी, मैं अपने आर्किटेक्चर पर भी सोच सकता हूं ... – gmile

2

यदि यह एक आप एक द्विआधारी खोज एल्गोरिथ्म (O(log n)) इस्तेमाल कर सकते हैं अनुसार क्रमबद्ध सरणी है। उदाहरण के लिए, इस कार्यक्षमता के साथ ऐरे-क्लास का विस्तार:

class Array 
    def b_search(e, l = 0, u = length - 1) 
    return if lower_index > upper_index 

    midpoint_index = (lower_index + upper_index)/2 
    return midpoint_index if self[midpoint_index] == value 

    if value < self[midpoint_index] 
     b_search(value, lower_index, upper_index - 1) 
    else 
     b_search(value, lower_index + 1, upper_index) 
    end 
    end 
end 
+1

यू लगता है कि यह पढ़ने के लिए आसान है? उत्तर के पीछे तर्क संदेश को एक आसान तरीके से वितरित करना है और आप अपना बिंदु स्पष्ट रूप से कर सकते हैं? – YoniGeek

+3

यह वास्तव में पढ़ने के लिए मुश्किल नहीं है। पहला भाग, अगर निचला बाउंड ऊपरी बाउंड से बड़ा है (रिकर्सन दायर किया गया है) लौटाएं। दूसरा भाग जांचता है कि अगर हमें उस बिंदु पर मूल्य के साथ मिडपॉइंट एम की तुलना करके बाईं तरफ या दाएं तरफ की आवश्यकता है। अगर हमारे पास वह जवाब नहीं है जो हम चाहते हैं, तो हम पुन: काम करते हैं। – ioquatix

+0

मुझे लगता है कि यह संपादन के बजाय लोगों की अहंकार के लिए बेहतर है। –

199

इंडेक्स या रिन्डेक्स का उपयोग क्यों नहीं करें?

array = %w(a b c d e) 
# get FIRST index of element searched 
puts array.index('a') 
# get LAST index of element searched 
puts array.rindex('a') 

सूचकांक: http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-index

rindex: http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-rindex

+12

यह वही है जो ओपी ने कहा था कि वे अपनी सरणी के बड़े आकार के कारण नहीं चाहते थे। ऐरे # इंडेक्स ओ (एन) है और ऐसा करने पर कई बार प्रदर्शन पर मार डाला जाएगा। हैश लुकअप ओ (1) है। – Tim

+4

@tim, ठीक है, मुझे अपने जवाब के समय याद नहीं है कि यह ** एक ही ** प्रश्न था, शायद ओपी ने बाद में प्रश्न को संशोधित किया, जो इस उत्तर को अमान्य कर देगा। – Roger

+3

क्या यह नहीं कहेंगे कि इसे किसी विशिष्ट समय पर संपादित किया गया था? – Tim

2

@ सावा के जवाब का एक संयोजन और टिप्पणी वहाँ सूचीबद्ध आप सरणी पर एक "जल्दी" सूचकांक और rindex को लागू कर सकता है ले रहा है कक्षा।

class Array 
    def quick_index el 
    hash = Hash[self.map.with_index.to_a] 
    hash[el] 
    end 

    def quick_rindex el 
    hash = Hash[self.reverse.map.with_index.to_a] 
    array.length - 1 - hash[el] 
    end 
end 
9

अन्य उत्तरों एक सरणी में कई बार सूचीबद्ध प्रविष्टि की संभावना को ध्यान में रखते हैं। यह एक हैश वापस आ जाएगी जहां प्रत्येक कुंजी सरणी में एक अनूठा वस्तु है और प्रत्येक मूल्य सूचकांक की एक सरणी है कि जहां किसी चीज़ रहती है से मेल खाती है है:

a = [1, 2, 3, 1, 2, 3, 4] 
=> [1, 2, 3, 1, 2, 3, 4] 

indices = a.each_with_index.inject(Hash.new { Array.new }) do |hash, (obj, i)| 
    hash[obj] += [i] 
    hash 
end 
=> { 1 => [0, 3], 2 => [1, 4], 3 => [2, 5], 4 => [6] } 

यह डुप्लिकेट प्रविष्टियों के लिए एक त्वरित खोज के लिए अनुमति देता है:

indices.select { |k, v| v.size > 1 } 
=> { 1 => [0, 3], 2 => [1, 4], 3 => [2, 5] } 
1

यदि आपके सरणी में प्राकृतिक आदेश बाइनरी खोज का उपयोग करता है।

बाइनरी खोज का उपयोग करें।

बाइनरी खोज में O(log n) पहुंच का समय है।

यहाँ कैसे द्विआधारी खोज का उपयोग करने पर कदम उठाए जाते हैं,

  • आप सरणी के आदेश क्या है? उदाहरण के लिए, क्या यह नाम से क्रमबद्ध है?
  • उपयोग bsearch तत्वों को खोजने या सूचकांक

कोड उदाहरण

# assume array is sorted by name! 

array.bsearch { |each| "Jamie" <=> each.name } # returns element 
(0..array.size).bsearch { |n| "Jamie" <=> array[n].name } # returns index 
संबंधित मुद्दे