2016-04-11 9 views
6

है, मैं एक ऐसा फ़ंक्शन बनाने की कोशिश कर रहा हूं जो स्ट्रिंग से प्रत्येक n'th तत्व को छोड़ देता है।हास्केल - फ़ंक्शन में एक खाली वर्ण

dropEvery :: String -> Int -> String 
dropEvery str n = map (\(char, indx) -> if indx `mod` n /= 0 then char else ' ') (zip str [1..]) 

अभी यह बस हर n'th तत्व एक स्थान के साथ बदलता है, लेकिन मैं क्या "और" के बाद डाल करने के लिए अगर मैं इसे एक "खाली चार" वापस करना चाहते चाहिए। मैं समझता हूं कि ऐसी चीज हास्केल में मौजूद नहीं है, इसलिए सवाल यह है कि - मुझे कुछ भी वापस न करने के लिए हास्केल को कैसे बताना चाहिए और बस अगले चार पर जाएं?

उत्तर

7

तुम बस map साथ ऐसा नहीं कर सकते , परिभाषा के अनुसार यह उस संग्रह की लंबाई को बदल नहीं सकता है जिस पर इसे लागू किया गया है। हालांकि, आप इसे concatMap पर स्विच करके बहुत अधिक परिवर्तन किए बिना काम पर ला सकते हैं। इस फ़ंक्शन को आपके फ़ंक्शन की आवश्यकता होती है जिसे आप मानचित्रण कर रहे हैं, एक सूची लौटाते हैं, फिर यह सभी परिणामों को एक साथ जोड़ता है। आपको बस इतना करना होगा कि

dropEvery str n = 
    concatMap (\(char, indx) -> if indx `mod` n /= 0 then [char] else []) (zip str [1..]) 
+0

मैंने "अन्य]" के बाद "[]" डालने का प्रयास किया, लेकिन निश्चित रूप से टाइप त्रुटियों को समाप्त कर दिया। concatMap एक अच्छा विचार है। –

+0

@ राउलपिलेव समस्या यह मानने से आती है कि "खाली 'चार' कहा जाता है। यह एक "खाली' Int' "या" खाली 'बूल' जैसा होगा, आपके पास' Int' हो सकता है जो 0 है, लेकिन ऐसा कोई नहीं है जिसके पास कोई मूल्य न हो (न कि 'अपरिभाषित' की गणना न हो) । खालीपन के लिए, आपको एक कंटेनर चाहिए। स्ट्रिंग्स कंटेनर हैं, क्योंकि वे केवल 'चर' की एक सूची हैं, इसलिए एक फ़ंक्शन '(चार, Int) -> [char]' के साथ, आप '[char, int) पर' concatMap' का उपयोग कर सकते हैं। ] एक '[चार] 'बाहर निकलने के लिए। – bheklilr

5

map सूची की संरचना को संरक्षित करता है, जबकि आपके संचालन तत्वों को हटाकर इसे संशोधित करते हैं। इसका मतलब है आप map उपयोग नहीं कर सकते, लेकिन आप जो आपको एक समारोह आप किन तत्वों उत्पादन से निकालना चाहते हैं के लिए Nothing रिटर्न प्रदान करने के लिए अनुमति देता है mapMaybe उपयोग कर सकते हैं:

import Data.Maybe (mapMaybe) 
dropEvery str n = mapMaybe (\(char, indx) -> if indx `mod` n /= 0 then Just(char) else Nothing) (zip str [1..]) 
+0

मैं कुछ परीक्षण सुनिश्चित करने के लिए चलाने के लिए होगा, लेकिन यह मेरा – bheklilr

+0

की तुलना में एक अधिक कुशल समाधान यह काफी वास्तव में मैं क्या देख रहा था है हो सकता है। मैं "कुछ भी नहीं" और "जस्ट (चार)" का उपयोग करने के बारे में सोच रहा था, लेकिन यह सुनिश्चित नहीं था कि "अपेक्षित प्रकार से मिलान नहीं हो सका" त्रुटियों के बिना कैसे। "MapMaybe" इसे हल करता है। इसके अलावा, अब मैं समझता हूं कि मानचित्र फ़ंक्शन कितना बेहतर काम करता है। धन्यवाद। –

3

आप mod के बिना ऐसा कर सकते हैं। मैं इसे अधिक मूर्खतापूर्ण बनाने के लिए तर्कों के क्रम को फ़्लिप करने जा रहा हूं।

dropEvery :: Int -> [a] -> [a] 
dropEvery n xs = map fst . filter ((/= n) . snd) $ zip xs (cycle [1..n]) 

तो गति महत्वपूर्ण है, यह संभावना सबसे स्पष्ट प्रत्यावर्तन या foldr साथ इस तकनीक का उपयोग करने के लिए कुशल होगा। कुछ इस तरह:

dropEvery n xs = foldr go (`seq` []) xs n where 
    go _ r 1 = r n 
    go x r k = x : r (k - 1) 
संबंधित मुद्दे