2011-04-10 18 views
8

मैं map और reduce के कार्यान्वयन को रूबी में अनुकरण करना चाहता हूं, जैसे कि यह सत्यापित करने के लिए कि विचार कम से कम काम करता है।मानचित्र के साथ समस्या को हल करने के लिए

मुझे निम्न समस्या है।

List1 
3 - A 
4 - B 
5 - C 
7 - D 
8 - F 

List2 
2 - A 
8 - B 
6 - C 
9 - D 
4 - E 

मैं एक आम सूची है कि दो सूचियों में आम अक्षर के साथ जुड़े संख्याओं का योग भी शामिल है का निर्माण करने की जरूरत है:: मैं दो तत्वों की सूची है

commonList 
5 - A 
12 - B 
11 - C 
16 - D 

मैं एक बनाना चाहते इस समस्या को हल करने के लिए map और reduce संचालन के साथ रूबी स्क्रिप्ट। मैं इस समस्या से निपटने के लिए अनिश्चित हूं या रूबी स्क्रिप्ट में इसे अनुकरण करने के लिए किस प्रक्रिया का पालन करना है।

किसी भी मदद की सराहना की।

उत्तर

2

आप MapReduce विकिपीडिया लेख में दिए गए तत्वों पर विचार करके की कोशिश कर सकते:

  • एक इनपुट पाठक - अपने मामले में यह शायद अपने इनपुट हैश से [key, value] जोड़ी पर एक विधि कॉल किया जाएगा।
  • एक मानचित्र समारोह - आप पहले से ही कुंजी आप के द्वारा अपने डेटा प्रसंस्करण किया जाना चाहिए है, तो अपने map कार्यकर्ता बस वापसी होगी [key, value] जोड़ी यह एक इनपुट
  • एक विभाजन समारोह के रूप में मिल गया है - एक तरीका है जिसके आधार पर एक को कम कार्यकर्ता आवंटित होगा कुंजी पर आपके मामले में यह केवल key.hash % REDUCER_COUNT हो सकता है।
  • तुलनात्मक फ़ंक्शन - मुझे नहीं लगता कि यह आपके मामले में लागू है क्योंकि आपको किसी भी विशेष क्रम में संसाधित होने के लिए मूल्यों की आवश्यकता नहीं है।
  • एक कमी समारोह - [key, list] जोड़ी दिया जाएगा, कुंजी से जुड़े मूल्यों की सूची होने की सूची दी जाएगी। यह सूची list की राशि वापस कर देगी यदि सूची एक से अधिक तत्व लंबी है (जैसा कि आप केवल इनपुट इनपुट दोनों प्रक्रियाओं में दिखाई देने वाले तत्व चाहते हैं)।
  • एक आउटपुट लेखक - आपके उदाहरण में सादा हैश हो सकता है।

और here's उपरोक्त के मेरे (अधिक) सरलीकृत कार्यान्वयन।

+0

मैं अपने समाधान कोशिश कर रहा हूँ, लेकिन मैं इस लाइन के साथ एक त्रुटि हो रही है: [कुंजी, list.inject (और: +)]। मैं इस त्रुटि मिलती है: "लेखन त्रुटि: गलत तर्क प्रकार प्रतीक (उम्मीद प्रोक)" – Flethuseo

+0

आप शायद पुराने रूबी का उपयोग कर रहे हैं। 'List.inject {| acc, i | का प्रयोग करें एसीसी + i} 'बदले में। –

2

मान लिया जाये कि हम अन्य सभी नक्शे-कम करने के कार्य को लागू किया है (इनपुट पाठक, उत्पादन लेखक, वैश्विक तरह, ...), इन map और reduce लोगों होगा:

def map(input) 
    input.each do |count, letter| 
    yield [letter, count] 
    end 
end 

def reduce(letter, partial_counts) 
    result = if partial_counts.size == 2 
    partial_counts[0] + partial_counts[1] 
    end 

    yield result 
end 

map फ़ंक्शन yield एक जोड़ी (letter, count) होगा, जिसे बाद में समूहीकृत किया जाएगा। फिर map एस reduce से प्राप्त प्रत्येक letter के लिए उस letter के लिए map द्वारा उत्पन्न प्रत्येक गणना वाली एक सरणी प्राप्त होगी। जैसा कि आप दोनों हीशों पर पत्र होने पर केवल उपज करना चाहते हैं, हमें एस को partial_counts पर दो बार अंत में गणना करने के लिए इसका उपयोग करने के लिए उपयोग करने की आवश्यकता है। reduce फ़ंक्शन कई तरीकों से कार्यान्वित किया जा सकता है। मैंने इसे समझने के लिए जितना संभव हो उतने सरल बनाने की कोशिश की है, हालांकि यह कार्यान्वयन इस समस्या के लिए बहुत समायोजित है।

इन map और reduce कार्यान्वयन का उपयोग कुंजी और उल्टे मूल्य के साथ पिछले हैश, जो और अधिक समझ में आता है, वहाँ के रूप में एक ही गिनती के साथ कई पत्र हो सकता है वापस आ जाएगी। इनपुट बेहतर होगा अगर यह उलटा कुंजी और मूल्य भी होगा।

def map(input) 
    input.each do |letter, count| 
    yield [letter, count] 
    end 
end 

या

def map(input) 
    input.each do |i| 
    yield i 
    end 
end 
2
list_1 = ["3 - A", "4 - B", "5 - C", "7 - D", "8 - F"] 

list_2 = ["2 - A", "8 - B", "6 - C", "9 - D", "4 - E"] 

(list_1 + list_2).map do |str| 
    # change array of strings to array in the form of [[name, value], ...] 
    str =~ /(\d+) - (.*)/ && [$2, $1.to_i] 
end.reduce({}) do |memo, obj| 
    # use a temporary Hash to sum up the values; 
    # the value is an array in the form of [value_counter, iteration_counter] 
    prev = memo[obj.first] || [0, 0] 
    memo[obj.first] = [prev.first + obj.last, prev.last + 1] 
    memo 
end.map do |key, value| 
    # convert to array in original format or 
    # nil, if occurred only once 
    value.last > 1 ? "#{key} - #{value.first}" : nil 
end.compact 

=> ["A - 5", "B - 12", "C - 11", "D - 16"] 

इस कोड को रूबी की map और reduce तरीकों का उपयोग करता है, लेकिन सीधे पर यह सब कर रही है: इस तरह, map(letter, count) की प्रत्येक जोड़ी उपज के रूप में सरल किया जाएगा एक हैश बहुत अधिक सुरुचिपूर्ण होगा।

2

का उपयोग आईआरबी (माणिक 1.9.2-P180):

list = [ {a:2, b:1, d:3}, {a:3, b:2, c:3}, {a:4, b:1, c:3} ] 
=> [{:a=>2, :b=>1, :d=>3}, {:a=>3, :b=>2, :c=>3}, {:a=>4, :b=>1, :c=>3}] 

Hash[list.map(&:keys).inject(&:&).map{|key| [key,list.map{|arr| arr[key]}.inject(&:+)]}] 
=> {:a=>9, :b=>4} 

इस समाधान एकाधिक सरणियों के साथ काम करता है (2 +) यह आम कुंजी पाता है और उन्हें परिणामों

के हैश

की ओर लौटने का योग (आम हिस्सा चाबियाँ इकट्ठा होते हैं और लगता है) आम कुंजी पाते हैं:

list.map(&:keys).inject(&:&) 

(कुंजी द्वारा चुनिंदा मूल्यों और उन्हें योग) कुंजी के लिए योग को खोजने के लिए:

list.map{|arr| arr[key]}.inject(&:+)] 

जोड़े [[:a,9], [:b,4]] की सरणी से हैश निर्माण करने के लिए:

results = [[:a,9], [:b,4]] 
Hash[ results ] 

मैं इस एक लाइनर्स के लिए गहरे लाल रंग का प्यार!

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