2011-03-06 13 views
8

मैंने इस विधि को एक सरणी में सबसे लंबा शब्द खोजने के लिए बनाया है, लेकिन मुझे आश्चर्य है कि ऐसा करने का एक बेहतर तरीका है या नहीं। मैं रूबी के लिए काफी नया हूं, और इसे inject विधि सीखने के लिए एक अभ्यास के रूप में किया।सरणी में रूबी सबसे लंबा शब्द

यह या तो सरणी में सबसे लंबा शब्द या बराबर सबसे लंबे शब्दों की सरणी देता है।

class Array 
    def longest_word 
    # Convert array elements to strings in the event that they're not. 
    test_array = self.collect { |e| e.to_s } 
    test_array.inject() do |word, comparison| 
     if word.kind_of?(Array) then 
     if word[0].length == comparison.length then 
      word << comparison 
     else 
      word[0].length > comparison.length ? word : comparison 
     end 
     else 
     # If words are equal, they are pushed into an array 
     if word.length == comparison.length then 
      the_words = Array.new 
      the_words << word 
      the_words << comparison 
     else 
      word.length > comparison.length ? word : comparison 
     end 
     end 
    end 
    end 
end 

उत्तर

27

मैं क्या करना होगा

class Array 
    def longest_word 
    group_by(&:size).max.last 
    end 
end 
+1

अगर आप वाकई केवल तार कर रहे हैं, तो आप इसे 'self.group_by (और लंबाई) के रूप में लिख सकते हैं .max.last' वरना आप' self.group_by {तरह फोन to_s' एक अतिरिक्त 'आवश्यकता होगी | एल | el.to_s .size} .max.last'। और अंत में, जब आपके पास केवल एक तत्व होता है तो एक स्ट्रिंग को वापस करने के लिए, आप 'longest_word.size> 1 कर सकते हैं? लौटने से पहले longest_word: longest_word.first'। –

+0

अच्छा! मैंने कोड को अधिक संक्षेप में बनाने की स्वतंत्रता ली, लेकिन अगर आपको शैली –

+0

पसंद नहीं है तो कृपया वापस लौटें। ओपी ने सवाल में कहा कि उसने 'इंजेक्ट' सीखने के लिए ऐसा किया है, और यह स्पष्ट नहीं है कि वह देख रहा था या नहीं 'इंजेक्ट' या बस एक बेहतर तरीका अवधि का उपयोग करने के बेहतर तरीके के लिए। आपकी दूसरी व्याख्या और @Mladen Jablanović के पहले के लिए एक बहुत अच्छा जवाब है। दोनों को मेरा +1 मिलता है। –

6

रूबी के पास अधिकतम मूल्य वाले किसी सूची में तत्व लौटने के लिए एक मानक विधि है।

anArray.max{|a, b| a.length <=> b.length} 

या आप अधिकतम लंबाई के साथ सभी तत्वों को प्राप्त करने के लिए max_by विधि

anArray.max_by(&:length) 

उपयोग कर सकते हैं

max_length = anArray.max_by(&:length).length 
all_with_max_length = anArray.find_all{|x| x.length = max_length} 
+0

यह अच्छा है, लेकिन ओ पी "। बस इंजेक्षन विधि सीखने के लिए एक व्यायाम के रूप ऐसा किया" –

+3

दोनों ही तरीकों से केवल एक ही तत्व है, कुछ समान रूप से लंबाई तार की नहीं एक सरणी वापस जाएँ। जब एक सरणी पर सीधे लागू होता है –

1

एक दो लाइनर:

vc = ['asd','s','1234','1235'].sort{|a,b| b.size <=> a.size} 
vc.delete_if{|a| a.size < vc.first.size} 


#Output 
["1235", "1234"] 

या यदि आप इंजेक्ट का उपयोग करना चाहते हैं, यह आपके विचार का उपयोग करता है, लेकिन इसकी एम अयस्क छोटा

test_array.inject{ |ret,word| 
    ret = [ret] unless ret.kind_of?(Array) 

    ret << word if word.size == ret.first.size 
    ret = [word] if word.size > ret.first.size 
    ret 
} 
+0

इस विधि idempotent नहीं है। शायद आप जो उम्मीद करेंगे वह नहीं। आप यहां 'क्लोन' का उपयोग कर सकते हैं।लेकिन समाधान ठीक है, और शायद नहीं भी धीमी ('group_by' निर्मित विधि के क्रियान्वयन विवरण जानने के बिना) –

+1

@Holger:' group_by' सरणी लुकअप का उपयोग करता है, तो यह मूल रूप 'हे (एन)' है, जबकि 'सॉर्ट' धीमा है। –

+0

'delete_if' के बजाय, आप' take_while' का उपयोग कर सकते हैं जो जैसे ही यह एक छोटे से शब्द तक पहुंच जाएगा। –

1
module Enumerable 
    def longest_word 
    (strings = map(&:to_s)). 
     zip(strings.map(&:length)). 
     inject([[''],0]) {|(wws, ll), (w, l)| 
     case l <=> ll 
     when -1 then [wws, ll] 
     when 1 then [[w], l] 
     else   [wws + [w], ll] 
     end 
     }.first 
    end 
end 

यह विधि केवल सामान्य Enumerable तरीकों पर निर्भर करता है, वहाँ कुछ भी नहीं Array इसके बारे में विशिष्ट है, इसलिए हम इसे खींच सकते हैं Enumerable मॉड्यूल, जहां यह भी Set या Enumerator रों लिए उपलब्ध हो जाएगा में, न केवल Array एस।

+0

यह केवल एक तत्व देता है, समान आकार वाले शब्दों की सरणी नहीं। – steenslag

+0

@steenslag: हाँ, ध्यान देने के लिए धन्यवाद। विधि नाम ने मुझे थोड़ा सा फेंक दिया, मुझे एक ऐसी विधि की उम्मीद होगी जो कई शब्दों को 'longest_words' (बहुवचन) कहलाए। –

4

यहाँ inject का उपयोग कर एक (एक खाली सरणी के लिए काम नहीं करता है) है:

words.inject(['']){|a,w| 
    case w.length <=> a.last.length 
    when -1 
    a 
    when 0 
    a << w 
    when 1 
    [w] 
    end 
} 

जो उन लोगों के लिए

words.inject(['']){|a,w| 
    [a + [w], [w], a][w.length <=> a.last.length] 
} 

को छोटा किया जा सकता गोल्फ पसंद है।

+0

असल में, यह * एक खाली सरणी के लिए काम करना चाहिए, यह (एक) बिंदु (ओं) स्पष्ट रूप से संचयक के लिए प्रारंभिक मूल्य की आपूर्ति करने के बिंदु (ओं) है। –

+0

मेरे संस्करण में, मैंने किसी भी तरह सोचा था कि यह संचयक के माध्यम से शब्द लंबाई को थ्रेड करने के लिए बहुत साफ होगा, लेकिन इसने इसे बिल्कुल साफ़ नहीं किया है :-) आपका बहुत अच्छा दिखता है। –

+0

रिक्त सरणी के लिए काम करने के लिए, किसी को एक खाली सरणी के साथ 'इंजेक्ट' करना होगा (एक स्ट्रिंग स्ट्रिंग युक्त सरणी के बजाय), और थोड़ा और अंदर ब्रांचिंग को जटिल बनाना होगा। लेकिन 'इंजेक्ट' सीखने के उद्देश्य से, मैंने सोचा कि यह पर्याप्त था। –

0

यह समाधान, एक सरणी में सबसे लंबे समय तक तार जमा करने के लिए सुई विधि का उपयोग करता है तो उच्चतम लंबाई के साथ लोगों को चुनता है।

जानवरों = [ "माउस", "बिल्ली", "पक्षी", "भालू", "मूस"]

animals.inject (Hash.new {| ज, कश्मीर | ज [k] = [ ]}) {| एसीसी, ई | एसीसी [e.size] < < ई; एसीसी} .sort.last [1]

यह रिटर्न: [ "माउस" "माउस"]

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