হাস্কেলের স্ট্রিং কীভাবে বিভক্ত করবেন?


163

হাস্কেলের স্ট্রিংকে বিভক্ত করার কোনও স্ট্যান্ডার্ড উপায় আছে কি?

linesএবং wordsএকটি স্পেস বা নিউলাইন বিভক্ত করা থেকে দুর্দান্ত কাজ, কিন্তু অবশ্যই একটি কমাতে বিভক্ত করার একটি আদর্শ উপায় আছে?

আমি এটি গুগলে খুঁজে পাইনি।

নির্দিষ্ট হতে, আমি কিছু জন্য যেখানে থাকবো 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
অন্যথায় যদি বাহ্যিক প্যাকেজগুলি গ্রহণযোগ্য হয় তবে মিসিংএইচ একটি বিভক্ত ফাংশনও সরবরাহ করে: হ্যাকেজ.হেসেকেল.আর.প্যাকেজস / অর্চিভ / মিসিংএইচ / ১.২.০.০ / ডক / এইচটিএমএল… এই প্যাকেজটি প্রচুর পরিমাণে অন্যান্য "সুন্দর-সুন্দর" ফাংশন সরবরাহ করে এবং আমি দেখতে পেয়েছি যে বেশ কিছু প্যাকেজ এটির উপর নির্ভর করে।
ইমানুয়েল টাজারি

41
বিভক্ত প্যাকেজটি এখন সাম্প্রতিক প্রকাশিত হিসাবে হ্যাশেল প্ল্যাটফর্মের বাইরে রয়েছে।
ইন্টারনেট

14
ডেটা.লিস্ট.স্প্লিট (স্প্লিটঅন) আমদানি করুন এবং শহরে যান। স্প্লিটঅন :: একিউ এ => [এ] -> [এ] -> [[এ]]
ইন্টারনেট

1
আপনি এটি ডাউনলোড করার পরে @ রুসঅববট বিভক্ত প্যাকেজটি হ্যাসেল প্ল্যাটফর্মের অন্তর্ভুক্ত করা হয়েছে ( হাস্কেল.আর / প্ল্যাটফর্ম / কনটেন্টস html ) তবে এটি আপনার প্রকল্পটি নির্মাণের সময় স্বয়ংক্রিয়ভাবে লোড হয় না is যোগ splitকরার জন্য build-dependsতারপর উদাঃ আপনার চক্রান্ত করা ফাইলের মধ্যে তালিকা, যদি আপনার প্রকল্পের হ্যালো বলা হয়, hello.cabalনিচের ফাইল executable helloবেস, split` (নোট দুই স্থান ইন্ডেন্ট): লাইন মত `বিল্ড-নির্ভর একটি লাইন করা। তারপরে cabal buildকমান্ডটি ব্যবহার করে বিল্ড করুন । Cf. haskell.org/cabal/users-guide/…
Expos

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

আপনি যদি ডেটা টেক্সট ব্যবহার করেন তবে স্প্লিটঅন রয়েছে:

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
@ রসআব্বট সম্ভবত textপ্যাকেজের উপর নির্ভরতা বা এটি ইনস্টল করতে হবে। যদিও অন্য একটি প্রশ্নে অন্তর্ভুক্ত হবে।
এমমানুয়েল টাজারি

'চর' প্রত্যাশিত প্রকারের সাথে 'টি.অনুবাদ' টাইপটি মেলাতে পারেনি: [চর] প্রকৃত প্রকার: [টি.এক্সেক্সট]
অ্যান্ড্রু কোস্টার

19

মডিউলটিতে পাঠ্য.রেজেক্স (হাস্কেল প্ল্যাটফর্মের অংশ) রয়েছে, এখানে একটি ফাংশন রয়েছে:

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

যা নিয়মিত প্রকাশের ভিত্তিতে একটি স্ট্রিং বিভক্ত হয় l এপিআই হ্যাকেজ পাওয়া যাবে


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

আমি স্টিভের উত্তর সম্মুখের একটি মন্তব্য যোগ করতে কিভাবে জানি না, কিন্তু আমি বলতে চাই
  GHC লাইব্রেরি ডকুমেন্টেশন ,
এবং সেখানে বিশেষভাবে
  Data.List মধ্যে Sublist ফাংশন

যা কেবলমাত্র সরল হাস্কেল রিপোর্ট পড়ার চেয়ে রেফারেন্স হিসাবে অনেক ভাল।

সাধারণভাবে, কখন খাওয়ানোর জন্য একটি নতুন সাবলিস্ট তৈরি করতে হবে তার বিধি সহ একটি ভাঁজও এটি সমাধান করা উচিত।


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
দয়া করে, স্ট্রিংগুলিকে বিভক্ত করতে নিয়মিত এক্সপ্রেশন ব্যবহার করবেন না। ধন্যবাদ.
কিরেলেগিন

@ কিরেলাগিন, কেন এই মন্তব্য? আমি হাস্কেল শিখছি, এবং আমি আপনার মন্তব্যের পিছনে যৌক্তিক জানতে চাই।
এনরিকো মারিয়া ডি অ্যাঞ্জেলিস

@ আন্দ্রে, আমি আমার প্রথম লাইন চালাতে না পারার একটি কারণ আছে ghci?
এনরিকো মারিয়া ডি অ্যাঞ্জেলিস

1
নিয়মিত প্রকাশগুলি স্ট্রিং মেলানোর জন্য একটি শক্তিশালী সরঞ্জাম @ যখন আপনি অ-তুচ্ছ কিছু মেলাচ্ছেন তখন এগুলি ব্যবহার করা বোধগম্য হয়। যদি আপনি কেবল অন্য নির্দিষ্ট স্ট্রিংয়ের মতো তুচ্ছ হিসাবে কোনও স্ট্রিংকে বিভক্ত করতে চান তবে নিয়মিত এক্সপ্রেশন ব্যবহার করার প্রয়োজন নেই - এটি কেবল কোডটিকে আরও জটিল এবং সম্ভবত ধীর করে দেবে।
কিরেলেগিন

"দয়া করে, স্ট্রিংগুলিকে বিভক্ত করতে নিয়মিত এক্সপ্রেশন ব্যবহার করবেন না।" ডাব্লুটিএফ, কেন নয় ??? একটি নিয়মিত প্রকাশের সাথে একটি স্ট্রিং বিভক্ত করা একদম যুক্তিসঙ্গত জিনিস। অনেকগুলি তুচ্ছ ঘটনা রয়েছে যেখানে স্ট্রিংকে বিভক্ত করা প্রয়োজন তবে ডিলিমিটার সবসময় হুবহু এক রকম হয় না।
অ্যান্ড্রু কোস্টার 16

2

আমি এই বুঝতে সহজ:

split :: Char -> String -> [String]
split c xs = case break (==c) xs of 
  (ls, "") -> [ls]
  (ls, x:rs) -> ls : split c rs
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.