हास्केल में एक स्ट्रिंग कैसे विभाजित करें?


163

क्या हास्केल में एक स्ट्रिंग को विभाजित करने का एक मानक तरीका है?

linesऔर wordsअंतरिक्ष या न्यूलाइन पर विभाजित होने से महान काम करते हैं, लेकिन निश्चित रूप से अल्पविराम पर विभाजित करने का एक मानक तरीका है?

मैं इसे Hoogle पर नहीं ढूंढ सका।

विशिष्ट होने के लिए, मैं कुछ ऐसी चीज़ों की तलाश में हूँ जहाँ से split "," "my,comma,separated,list"रिटर्न मिले ["my","comma","separated","list"]


21
मैं वास्तव में Data.Listया भविष्य के रिलीज में भी इस तरह के एक समारोह के लिए चाहूंगा Prelude। यदि यह कोड-गोल्फ के लिए उपलब्ध नहीं है तो यह बहुत सामान्य और बुरा है।
फ़ूज

जवाबों:


135

इसके लिए एक पैकेज है जिसे स्प्लिट कहा जाता है ।

cabal install split

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

ghci> import Data.List.Split
ghci> splitOn "," "my,comma,separated,list"
["my","comma","separated","list"]

यह कई अन्य कार्यों के साथ आता है जो कि सीमांकक से मेल खाते हैं या कई सीमांकक हैं।


9
ठंडा। मुझे इस पैकेज की जानकारी नहीं थी। यह वह जगह है परम विभाजन पैकेज के रूप में यह आपरेशन पर अधिक नियंत्रण (परिणामों में ट्रिम अंतरिक्ष, परिणाम में छुट्टी विभाजक, लगातार निकालें विभाजक, आदि ...) देता है। सूचियों को विभाजित करने के बहुत सारे तरीके हैं, एकल फ़ंक्शन में होना संभव नहीं है जो हर आवश्यकताओं का जवाब देगा, आपको वास्तव में उस तरह के पैकेज की आवश्यकता होगी। split
गावी

1
अन्यथा यदि बाहरी संकुल स्वीकार्य हैं, MissingH भी एक विभाजन समारोह प्रदान करता है: hackage.haskell.org/packages/archive/MissingH/1.2.0.0/doc/html/... पैकेज भी अन्य "अच्छा करने के लिए है" कार्यों के बहुत सारे प्रदान करता है यही कारण है कि और मुझे लगता है कि काफी कुछ पैकेज इस पर निर्भर करते हैं।
इमैनुएल टॉज़री

41
विभाजन पैकेज अब हाल के रिलीज के रूप में हैसेल प्लेटफॉर्म के अलावा है।
इंटरनेट

14
Data.List.Split (स्प्लिटऑन) आयात करें और शहर में जाएं। स्प्लिटऑन :: Eq a => [a] -> [a] -> [[a]]
इंटरनेट

1
जब आप इसे डाउनलोड करते हैं तो @RussAbbott विभाजन पैकेज हास्केल प्लेटफ़ॉर्म में शामिल होता है ( haskell.org/platform/contents.html ), लेकिन यह आपकी परियोजना बनाते समय स्वचालित रूप से लोड नहीं होता है। जोड़े splitको build-dependsतो में जैसे अपने कबाल फ़ाइल में सूची, यदि आपके परियोजना नमस्ते कहा जाता है, hello.cabalनीचे दिए गए फ़ाइल executable helloआधार, split` (नोट दो अंतरिक्ष मांगपत्र): लाइन की तरह `निर्माण निर्भर करता है एक लाइन डाल दिया। फिर cabal buildकमांड का उपयोग करके निर्माण करें । सी एफ haskell.org/cabal/users-guide/…
18

164

याद रखें कि आप प्रस्तावना कार्यों की परिभाषा देख सकते हैं!

http://www.haskell.org/onlinereport/standard-prelude.html

वहां देखते हुए, की परिभाषा wordsहै,

words   :: String -> [String]
words s =  case dropWhile Char.isSpace s of
                      "" -> []
                      s' -> w : words s''
                            where (w, s'') = break Char.isSpace s'

इसलिए, इसे एक ऐसे कार्य के लिए बदलें जो एक विधेय लेता है:

wordsWhen     :: (Char -> Bool) -> String -> [String]
wordsWhen p s =  case dropWhile p s of
                      "" -> []
                      s' -> w : wordsWhen p s''
                            where (w, s'') = break p s'

फिर इसे आप जो भी विधेय चाहते हैं, उसके साथ कहें!

main = print $ wordsWhen (==',') "break,this,string,at,commas"

31

यदि आप Data.Text का उपयोग करते हैं, तो स्प्लिटऑन है:

http://hackage.haskell.org/packages/archive/text/0.11.2.0/doc/html/Data-Text.html#v:splitOn

इसे हास्केल प्लेटफॉर्म में बनाया गया है।

उदाहरण के लिए:

import qualified Data.Text as T
main = print $ T.splitOn (T.pack " ") (T.pack "this is a test")

या:

{-# LANGUAGE OverloadedStrings #-}

import qualified Data.Text as T
main = print $ T.splitOn " " "this is a test"

1
@RussAbbott शायद आपको textपैकेज पर निर्भरता की आवश्यकता है या इसे स्थापित करें। हालांकि एक और सवाल में होगा।
इमैनुएल टौजरी

'चार' अपेक्षित प्रकार के साथ 'T.Text' का मिलान नहीं हो सका: [Char] वास्तविक प्रकार: [T.Text]
एंड्रयू कॉस्टर

19

मॉड्यूल Text.Regex (हास्केल प्लेटफ़ॉर्म का हिस्सा) में, एक फ़ंक्शन है:

splitRegex :: Regex -> String -> [String]

जो एक स्ट्रिंग को एक नियमित अभिव्यक्ति के आधार पर विभाजित करता है। हैक में एपीआई पाया जा सकता है ।


Could not find module ‘Text.Regex’ Perhaps you meant Text.Read (from base-4.10.1.0)
एंड्रयू कोस्टर

18

उपयोग करें Data.List.Split, जो उपयोग करता है split:

[me@localhost]$ ghci
Prelude> import Data.List.Split
Prelude Data.List.Split> let l = splitOn "," "1,2,3,4"
Prelude Data.List.Split> :t l
l :: [[Char]]
Prelude Data.List.Split> l
["1","2","3","4"]
Prelude Data.List.Split> let { convert :: [String] -> [Integer]; convert = map read }
Prelude Data.List.Split> let l2 = convert l
Prelude Data.List.Split> :t l2
l2 :: [Integer]
Prelude Data.List.Split> l2
[1,2,3,4]

14

इसको आजमाओ:

import Data.List (unfoldr)

separateBy :: Eq a => a -> [a] -> [[a]]
separateBy chr = unfoldr sep where
  sep [] = Nothing
  sep l  = Just . fmap (drop 1) . break (== chr) $ l

केवल एक ही चर के लिए काम करता है, लेकिन आसानी से विस्तार योग्य होना चाहिए।


10

किसी स्थान के लिए किसी एक वर्ण के सीधे प्रतिस्थापन का आयात किए बिना, लक्ष्य विभाजक wordsएक स्थान है। कुछ इस तरह:

words [if c == ',' then ' ' else c|c <- "my,comma,separated,list"]

या

words let f ',' = ' '; f c = c in map f "my,comma,separated,list"

आप मापदंडों के साथ एक फ़ंक्शन में बना सकते हैं। आप मेरी तरह कई मिलान पैरामीटर -से-मैच को समाप्त कर सकते हैं , जैसे:

 [if elem c ";,.:-+@!$#?" then ' ' else c|c <-"my,comma;separated!list"]

9
split :: Eq a => a -> [a] -> [[a]]
split d [] = []
split d s = x : split d (drop 1 y) where (x,y) = span (/= d) s

उदाहरण के लिए

split ';' "a;bb;ccc;;d"
> ["a","bb","ccc","","d"]

एक एकल ट्रेलिंग सीमांकक को गिरा दिया जाएगा:

split ';' "a;bb;ccc;;d;"
> ["a","bb","ccc","","d"]

6

मैंने कल हास्केल सीखना शुरू किया, इसलिए मुझे सही करें अगर मैं गलत हूं लेकिन:

split :: Eq a => a -> [a] -> [[a]]
split x y = func x y [[]]
    where
        func x [] z = reverse $ map (reverse) z
        func x (y:ys) (z:zs) = if y==x then 
            func x ys ([]:(z:zs)) 
        else 
            func x ys ((y:z):zs)

देता है:

*Main> split ' ' "this is a test"
["this","is","a","test"]

या शायद आप चाहते थे

*Main> splitWithStr  " and " "this and is and a and test"
["this","is","a","test"]

जो होगा:

splitWithStr :: Eq a => [a] -> [a] -> [[a]]
splitWithStr x y = func x y [[]]
    where
        func x [] z = reverse $ map (reverse) z
        func x (y:ys) (z:zs) = if (take (length x) (y:ys)) == x then
            func x (drop (length x) (y:ys)) ([]:(z:zs))
        else
            func x ys ((y:z):zs)

1
मैं एक बिल्ट-इन की तलाश कर रहा था split, अच्छी तरह से विकसित पुस्तकालयों के साथ भाषाओं द्वारा खराब किया जा रहा है। लेकिन फिर भी धन्यवाद।
एरिक विल्सन

3
आपने यह जून में लिखा था, इसलिए मुझे लगता है कि आप अपनी यात्रा में आगे बढ़ चुके हैं :) एक अभ्यास के रूप में, इन फ़ंक्शन को उलटा या लंबाई के बिना पुनर्लेखन करने की कोशिश करना क्योंकि इन कार्यों का उपयोग एक एल्गोरिथम जटिलता दंड को लागू करता है और एक अनंत सूची में आवेदन को भी रोकता है। मज़े करो!
टोनी मॉरिस

5

मुझे नहीं पता कि स्टीव के जवाब पर टिप्पणी कैसे जोड़नी है, लेकिन मैं
  जीएचसी पुस्तकालयों के प्रलेखन की सिफारिश करना चाहता हूं ,
और विशेष रूप से डेटा लिस्ट में
  सबलिस्ट कार्य करता हूं।

जो सादे हास्केल रिपोर्ट को पढ़ने की तुलना में एक संदर्भ के रूप में बहुत बेहतर है।

आम तौर पर, फ़ीड करने के लिए एक नई सबलिस्ट बनाने के लिए एक नियम के साथ तह, इसे भी हल करना चाहिए।


2

जवाब में दिए गए कुशल और पूर्व-निर्मित कार्यों के अलावा, मैं अपना खुद का जोड़ दूंगा जो कि हास्केल कार्यों के मेरे भंडार का हिस्सा हैं जो मैं अपने समय पर भाषा सीखने के लिए लिख रहा था:

-- Correct but inefficient implementation
wordsBy :: String -> Char -> [String]
wordsBy s c = reverse (go s []) where
    go s' ws = case (dropWhile (\c' -> c' == c) s') of
        "" -> ws
        rem -> go ((dropWhile (\c' -> c' /= c) rem)) ((takeWhile (\c' -> c' /= c) rem) : ws)

-- Breaks up by predicate function to allow for more complex conditions (\c -> c == ',' || c == ';')
wordsByF :: String -> (Char -> Bool) -> [String]
wordsByF s f = reverse (go s []) where
    go s' ws = case ((dropWhile (\c' -> f c')) s') of
        "" -> ws
        rem -> go ((dropWhile (\c' -> (f c') == False)) rem) (((takeWhile (\c' -> (f c') == False)) rem) : ws)

समाधान कम से कम पूंछ-पुनरावर्ती हैं ताकि वे एक ढेर अतिप्रवाह नहीं करेंगे।


2

घिसी में उदाहरण:

>  import qualified Text.Regex as R
>  R.splitRegex (R.mkRegex "x") "2x3x777"
>  ["2","3","777"]

1
कृपया, स्ट्रिंग्स को विभाजित करने के लिए नियमित अभिव्यक्तियों का उपयोग न करें। धन्यवाद।
किर्लगिन

@kirelagin, यह टिप्पणी क्यों? मैं हास्केल सीख रहा हूं, और मैं आपकी टिप्पणी के पीछे तर्कसंगत जानना चाहूंगा।
एनरिको मारिया डे एंजेलिस

@ और, क्या ऐसा कारण है कि मैं अपनी पहली पंक्ति भी नहीं चला सकता ghci?
एनरिको मारिया डे एंजेलिस

1
@EnricoMariaDeAngelis नियमित अभिव्यक्ति स्ट्रिंग मिलान के लिए एक शक्तिशाली उपकरण है। जब आप कुछ गैर-तुच्छ मिलान कर रहे हैं तो उनका उपयोग करना समझ में आता है। यदि आप किसी स्ट्रिंग को किसी अन्य निश्चित स्ट्रिंग के रूप में तुच्छ के रूप में विभाजित करना चाहते हैं, तो नियमित अभिव्यक्ति का उपयोग करने की बिल्कुल आवश्यकता नहीं है - यह केवल कोड को अधिक जटिल बना देगा और, संभावना है, धीमा।
किर्लगिन

"कृपया, स्ट्रिंग्स को विभाजित करने के लिए नियमित अभिव्यक्तियों का उपयोग न करें।" डब्ल्यूटीएफ, क्यों नहीं ??? नियमित अभिव्यक्ति के साथ एक स्ट्रिंग को विभाजित करना पूरी तरह से उचित काम है। बहुत सारे तुच्छ मामले हैं जहां एक स्ट्रिंग को विभाजित करने की आवश्यकता होती है, लेकिन सीमांकक हमेशा एक समान नहीं होता है।
एंड्रयू कोस्टर जूल

2

मुझे यह समझने में सरल लगता है:

split :: Char -> String -> [String]
split c xs = case break (==c) xs of 
  (ls, "") -> [ls]
  (ls, x:rs) -> ls : split c rs
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.