2009-02-24 10 views
8

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

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

चुनौती: सरणी के तत्वों को स्पष्ट रूप से लूप किए बिना कम करने के लिए।
इनपुट: -10 से 10 (0 को छोड़कर) से सभी पूर्णांक यादृच्छिक रूप से आदेश दिया गया।
वांछित आउटपुट: एक सरणी सकारात्मक या नकारात्मक संख्याओं की लकीर का प्रतिनिधित्व करती है। उदाहरण के लिए, एक -3 लगातार तीन नकारात्मक संख्याओं का प्रतिनिधित्व करता है। ए 2 लगातार दो सकारात्मक संख्याओं का प्रतिनिधित्व करता है।

नमूना स्क्रिप्ट:

original_array = (-10..10).to_a.sort{rand(3)-1} 
original_array.reject!{|i| i == 0} # remove zero 

streaks = (-1..1).to_a # this is a placeholder. 
# The streaks array will contain the output. 
# Your code goes here, hopefully without looping through the array 

puts "Original Array:" 
puts original_array.join(",") 
puts "Streaks:" 
puts streaks.join(",") 
puts "Streaks Sum:" 
puts streaks.inject{|sum,n| sum + n} 

नमूना आउटपुट:

Original Array: 
3,-4,-6,1,-10,-5,7,-8,9,-3,-7,8,10,4,2,5,-2,6,-1,-9 
Streaks: 
1,-2,1,-2,1,-1,1,-2,5,-1,1,-2 
Streaks Sum: 
0 


Original Array: 
-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7,8,9,10 
Streaks: 
-10,10 
Streaks Sum: 
0 

नोट कुछ चीजें:

  • धारियाँ सरणी धनात्मक और ऋणात्मक मानों बारी है।
  • तत्वों की संख्या streaks सरणी हमेशा 0 है (जैसा कि मूल का योग है)।
  • लकीर सरणी के शुद्ध मान का योग हमेशा 20.

आशा है कि स्पष्ट है है!

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

+0

सरणी के माध्यम से फिर से क्यों नहीं? आप इसके माध्यम से लूप किए बिना किसी सरणी की सामग्री को संसाधित करने की अपेक्षा कैसे करते हैं। यहां तक ​​कि यदि आप ऐसा करने के लिए एक विधि का उपयोग करते हैं, तो भी यह आंतरिक रूप से सरणी के माध्यम से लूप होगा। –

+0

आपको एहसास है कि आपके कोड उदाहरण में आपके द्वारा बुलाए गए हर तरीके वास्तव में सरणी के माध्यम से लूपिंग कर रहे थे ... – kgrad

+0

हाँ, बिल्कुल इसके माध्यम से लूप किए बिना सरणी को कम करने का कोई तरीका नहीं है ... पहुंचने का कोई तरीका नहीं होगा सामग्री। – cdmckay

उत्तर

1

रूबी 1.9 के बाद से इस समस्या को हल करने के लिए एक बहुत सरल तरीका है:

original_array.chunk{|x| x <=> 0 }.map{|a,b| a * b.size } 

Enumerable.chunk इच्छा समूह के सभी लगातार तत्वों एक ब्लॉक के आउटपुट द्वारा एक सरणी:

>> original_array.chunk{|x| x <=> 0 } 
=> [[1, [3]], [-1, [-4, -6]], [1, [1]], [-1, [-10, -5]], [1, [7]], [-1, [-8]], [1, [9]], [-1, [-3, -7]], [1, [8, 10, 4, 2, 5]], [-1, [-2]], [1, [6]], [-1, [-1, -9]]] 

यह लगभग ओपी क्या पूछता है, इसके परिणामस्वरूप समूहों को अंतिम लकीर सरणी प्राप्त करने के लिए गिना जाना चाहिए।

+0

धन्यवाद! यही वह है जिसे मैं मूल रूप से ढूंढ रहा था। –

4
original_array.each do |num| 
    if streaks.size == 0 
    streaks << num 
    else 
    if !((streaks[-1] > 0)^(num > 0)) 
     streaks[-1] += 1 
    else 
     streaks << (num > 0 ? 1 : -1) 
    end 
    end 
end 

यहाँ जादू ^ XOR ऑपरेटर है।

true^false #=> true 
true^true #=> false 
false^false #=> false 

तो अगर सरणी में पिछले संख्या शून्य संख्या कार्रवाई की जा रही की दिशा में हो रहा है, तो यह लकीर को जोड़ने, अन्यथा धारियाँ सरणी में जोड़ने के लिए एक नया लकीर शुरू करने के लिए। ध्यान दें कि साइन true^truefalse लौटाता है हमें पूरी अभिव्यक्ति को अस्वीकार करना होगा।

+0

लेकिन ... आप लूपिंग कर रहे हैं! –

+0

यह मेरे लिए सही नहीं लग रहा है। क्या आप गिनती या संक्षेप में हैं? – jcrossley3

+0

ओह, मैं थोड़ा गलत समझ गया। यह मूल्यों को बताता है, लकीर में उन्हें गिना जाता है। आप सही हे। मैं इसे ठीक कर दूंगा। –

6
new_array = original_array.dup 
<Squeegy's answer, using new_array> 

ता दा! मूल सरणी के माध्यम से कोई लूपिंग नहीं। हालांकि डुप्ली के अंदर यह एक एमईएमसीपीवाई है, जो मुझे लगता है कि असेंबलर स्तर पर लूप माना जा सकता है?

http://www.ruby-doc.org/doxygen/1.8.4/array_8c-source.html

संपादित करें:;)

+0

+1, दूसरों को बदतर के लिए कई अंक मिल गए हैं ... –

11

ठीक है, यहाँ, एक पंक्ति संस्करण है, तो है कि आप अधिक प्रसन्न:

streaks = original_array.inject([]) {|a,x| (a.empty? || x * a[-1] < 0 ? a << 0 : a)[-1] += x <=> 0; a} 

और अगर भी इंजेक्षन तुम्हारे लिए भी दीवाना है , यहां वास्तव में मूर्खतापूर्ण तरीका है:

streaks = eval "[#{original_array.join(",").gsub(/((\-\d+,?)+|(\d+,?)+)/) {($1[0..0] == "-" ? "-" : "") + $1.split(/,/).size.to_s + ","}}]" 

लेकिन मुझे लगता है यह बहुत स्पष्ट है कि आप कुछ और अधिक सरल के साथ बेहतर होते हैं:

streaks = [] 
original_array.each do |x| 
    xsign = (x <=> 0) 
    if streaks.empty? || x * streaks[-1] < 0 
    streaks << xsign 
    else 
    streaks[-1] += xsign 
    end 
end 

बहुत आसान जा रहा है समझते हैं और बनाए रखने के लिए के अलावा, "लूप" संस्करण के बारे में दो तिहाई में समय चलाता है इंजेक्शन संस्करण का, और eval/regexp एक के छठे के बारे में एक।

पुनश्च: यहाँ एक और संभावित रूप से दिलचस्प संस्करण है:

a = [[]] 
original_array.each do |x| 
    a << [] if x * (a[-1][-1] || 0) < 0 
    a[-1] << x 
end 
streaks = a.map {|aa| (aa.first <=> 0) * aa.size} 

यह दो गुजरता का उपयोग करता है, पहले, लकीर सरणियों की एक सरणी का निर्माण तो हस्ताक्षर किए आकार की एक सरणी के लिए सरणियों की सरणी परिवर्तित। रुबी 1.8.5 में, यह वास्तव में उपरोक्त इंजेक्शन संस्करण की तुलना में थोड़ा तेज है (हालांकि रूबी 1.9 में यह थोड़ा धीमा है), लेकिन उबाऊ पाश अभी भी सबसे तेज़ है।

+0

कोई टिप्पणी या दो का उपयोग कर सकता है। मुझे लगता है कि आपने इसे समझाया है, लेकिन कोड में टिप्पणियां डालने की ऐसी चीज है जिसे अक्सर उपेक्षित किया जाता है। –

1

अधिक स्ट्रिंग दुरुपयोग, एक ला ग्लेन मैकडॉनल्ड्स, केवल अलग:

runs = original_array.map do |e| 
    if e < 0 
    '-' 
    else 
    '+' 
    end 
end.join.scan(/-+|\++/).map do |t| 
    "#{t[0..0]}#{t.length}".to_i 
end 

p original_array 
p runs 
# => [2, 6, -4, 9, -8, -3, 1, 10, 5, -7, -1, 8, 7, -2, 4, 3, -5, -9, -10, -6] 
# => [2, -1, 1, -2, 3, -2, 2, -1, 2, -4] 
संबंधित मुद्दे