2011-09-19 13 views
8

मैं हास्केल के साथ संघर्ष कर रहा हूं, और चीजों पर पुनरावृत्ति करने के लिए रिकर्सन का उपयोग करने का विचार।यह स्निपेट हास्केल में कैसे अनुवाद करेगा?

उदाहरण के लिए, कैसे

// this might seem silly but I need to do it 
list1 = empty list 
list2 = list of numbers 
for i from 0 to N // N being a positive integer 
    for each number in list2 
     if number == i, add to list1 

'कार्यात्मक प्रतिमान' में अनुवाद होगा? किसी भी मार्गदर्शन की सराहना की जाएगी।

उत्तर

9

जा रहे कदम:

list2 = list of numbers 

हमें दिए गए के रूप में इस ले लेंगे, तो list2 अभी भी सिर्फ संख्या की एक सूची है।

for i from 0 to N // N being a positive integer 

हास्केल में यह करने के लिए सही तरीका एक सूची के साथ आम तौर पर है। आलस्य का मतलब है कि मूल्यों का उपयोग केवल तभी किया जाएगा जब उपयोग किया जाता है, इसलिए 0 से एन तक की सूची को पार करना आपके जैसा लूप जैसा ही होता है। तो, बस [0..n] चाल करेगा; हमें बस यह पता लगाने की जरूरत है कि इसके साथ क्या किया जाए।

for each number in list2 

को देखते हुए "के लिए प्रत्येक" हम मान सकते हैं कि हम list2 यहाँ की सम्पूर्णता पार करने के लिए की आवश्यकता होगी; हम इसके साथ क्या करते हैं, हम अभी तक नहीं जानते हैं।

if number == i, add to list1 

हम list1 निर्माण कर रहे हैं के रूप में हम चले तो आदर्श हम चाहते हैं कि अभिव्यक्ति की अंतिम परिणाम होना चाहता हूँ। इसका मतलब यह भी है कि प्रत्येक पुनरावर्ती कदम पर, हम परिणाम list1 होना चाहते हैं, हमारे पास "अब तक" है। ऐसा करने के लिए, हमें यह सुनिश्चित करने की आवश्यकता होगी कि हम प्रत्येक चरण के परिणाम को साथ ही साथ पास करते हैं।

तो, इसके बारे में मांस के लिए नीचे हो रही:

filter समारोह कुछ विधेय मिलान एक सूची के सभी तत्वों पाता है; हम filter (== i) list2 का उपयोग यहां प्राप्त करने के लिए करेंगे, इसके बाद हम पिछले चरण के परिणाम में संलग्न करें। तो प्रत्येक चरण इस तरह दिखेगा:

step :: (Num a) => [a] -> a -> [a] 
step list1 i = list1 ++ filter (== i) list2 

जो आंतरिक लूप को संभालता है। पीछे की तरफ कदम उठाने के लिए, हमें [0..n] सूची से प्रत्येक मान i के लिए इसे चलाने की आवश्यकता है, प्रत्येक चरण में list1 मान पास किया जा रहा है।यह ठीक है कि क्या गुना कार्यों के लिए कर रहे हैं, और इस मामले में step वास्तव में क्या हम एक छोड़ दिया गुना के लिए की जरूरत है:

list2 :: (Num a) => [a] 
list2 = -- whatever goes here... 

step :: (Num a) => [a] -> a -> [a] 
step list1 i = list1 ++ filter (== i) list2 

list1 :: (Num a) => a -> [a] 
list1 n = foldl step [] [0..n] 

आप सोच रहे हैं कि जहां प्रत्यावर्तन है, दोनों filter और foldl हमारे लिए है कि क्या कर रहे हैं । अंगूठे के नियम के रूप में, आमतौर पर प्रत्यक्ष रिकर्सन से बचने के लिए बेहतर होता है जब आपके लिए उच्च स्तरीय कार्य होते हैं।


कहा कि, एल्गोरिथ्म यहाँ कई मायनों में मूर्खतापूर्ण है, लेकिन मुझे लगता है कि में प्राप्त करने के लिए है क्योंकि यह लग रहा था इस तरह की और की तुलना में यह मदद मिलेगी अपने वास्तविक सवाल से विचलित होता नहीं चाहता था।

+0

क्यों एक स्पष्ट concatenation चरण पर तह करने के बजाय 'concatMap' का उपयोग नहीं करें? – bdonlan

+2

ध्यान दें कि इस मामले में, आप सूची समझ का उपयोग कर सकते हैं: [संख्या | i <- [1..N], संख्या <-list2, i == संख्या] जो आपके छद्म कोड का प्रत्यक्ष अनुवाद है। – ysdx

+0

एक महान उत्तर के लिए धन्यवाद। मुझे एहसास है कि मैंने जो स्निपेट पोस्ट किया है वह विचित्र है ... मैंने इससे किसी भी अर्थ को काफी हद तक मुंडा कर दिया। यह एक रेडिक्स सॉर्ट व्यायाम का हिस्सा है जो मैं कर रहा हूं। –

10

क्षमा करें, लेकिन मैं मदद नहीं कर सकता लेकिन एक बेहतर एल्गोरिथ्म का उपयोग करें ...

let goodNumber n = (0 <= n && n < N) 
let list1 = sort (filter goodNumber list2) 

संपादित करें: मसा में इस overkill का एक छोटा सा है, क्योंकि ओ पी एक को लागू करने के कोशिश कर रहा था पहली जगह में अलगाव छंटनी। कदम से

0
let list1 = sort [a | a<-list2, a>=0, a<=N] 

a<-list2 की पसंद अप List2 से प्रत्येक संख्या a>=0, a<=N जांच उठाया संख्या इन सभी की स्थिति अगर शर्तें पूरी होने पर, एक एक नई सूची में डाल एक बार सभी List2 के तत्वों इस प्रकार की जाँच की गई है और कर रहा है पूरा करता है एक नई सूची में डालें, हम इस पर एक प्रकार का परिणाम करते हैं परिणाम सूची 1

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