Haskell разбивает слова по пробелам - PullRequest
6 голосов
/ 16 августа 2011

Обратите внимание, что это не то же самое, что использование функции слов.

Я хотел бы преобразовать из этого:

"The quick brown fox jumped over the lazy dogs."

в это:

["The"," quick"," brown"," fox"," jumped"," over"," the"," lazy"," dogs."]

Обратите внимание, что разрывы в первом пробеле после каждого слова.

Лучшее, что я мог придумать, это:

parts "" = []
parts s  = if null a then (c ++ e):parts f else a:parts b
    where
    (a, b) = break isSpace s
    (c, d) = span isSpace s
    (e, f) = break isSpace d

Это выглядит немного не элегантно. Кто-нибудь может придумать лучший способ выразить это?

Ответы [ 7 ]

6 голосов
/ 16 августа 2011

edit - Извините, я не прочитал вопрос.Надеюсь, этот новый ответ сделает то, что вы хотите.

> List.groupBy (\x y -> y /= ' ') "The quick brown fox jumped over the lazy dogs."
["The"," quick"," brown"," fox"," jumped"," over"," the"," lazy"," dogs."]

Библиотечная функция groupBy принимает функцию предиката, которая сообщает вам, добавляете ли вы следующий элемент, y в предыдущий список,который начинается с x , или начинается новый список.

В этом случае нам не важно, с чего начался текущий список, мы только хотим начать новый список (т.е. сделатьпредикат оценивается как ложный), когда следующий элемент, y , является пробелом.

edit

nm указывает, что обработка нескольких пробелов не является правильной.В этом случае вы можете переключиться на Data.List.HT, который имеет семантику, которую вы хотите.

> import Data.List.HT as HT
> HT.groupBy (\x y -> y /= ' ' || x == ' ') "a  b c d"
["a","  b"," c"," d"]

другая семантика, которая делает эту работу, состоит в том, что x является последним элементомв предыдущем списке (к которому можно добавить y или создать новый список).

3 голосов
/ 16 августа 2011

Если вы выполняете много разных типов разделений, взгляните на пакет split . Пакет позволяет определить это разделение как split (onSublist [" "]).

1 голос
/ 16 августа 2011
words2 xs = head w : (map (' ':) $ tail w)
  where w = words xs

А вот со стрелками и аппликативными: (не рекомендуется для практического использования)

words3 = words >>> (:) <$> head <*> (map (' ':) . tail)

РЕДАКТИРОВАТЬ: мое первое решение неверно, потому что он съедает дополнительные пробелы. Вот правильный:

words4 = foldr (\x acc -> if x == ' ' || head acc == "" || (head $ head acc) /= ' '  
                             then (x : head acc) : tail acc
                             else [x] : acc) [""]
0 голосов
/ 10 ноября 2013

Вот оно.Наслаждайтесь!: D

 words' :: String -> [String]
    words' [] = []
    words' te@(x:xs) | x==' ' || x=='\t' || x=='\n' = words' xs
                     | otherwise                = a : words' b
      where
        (a, b) = break isSpace te
0 голосов
/ 17 августа 2011

Мне нравится идея разделения пакета, но split (onSublist [" "]) не делает то, что я хочу, и я не могу найти решение, которое разделяется на один или несколько пробелов.

Также как и решениеиспользуя Data.List.HT, но я бы хотел по возможности держаться подальше от зависимостей.

Чистейшее, что я могу придумать:

parts s 
    | null s    = []
    | null a    = (c ++ e) : parts f
    | otherwise = a        : parts b
    where
    (a, b) = break isSpace s
    (c, d) = span  isSpace s
    (e, f) = break isSpace d
0 голосов
/ 16 августа 2011
parts xs = foldr spl [] xs where
   spl x [] = [[x]]
   spl ' ' (xs:xss) = (' ':xs):xss    
   spl x xss@((' ':_):_) = [x]:xss    
   spl x (xs:xss) = (x:xs):xss   
0 голосов
/ 16 августа 2011

Вот мой дубль

break2 :: (a->a->Bool) -> [a] -> ([a],[a])
break2 f (x:(xs@(y:ys))) = if f x y then ([x],xs) else (x:u,us) 
                              where (u,us) = break2 f xs
break2 f xs = (xs, [])

onSpace x y = not (isSpace x) && isSpace y

words2 "" = []
words2 xs = y : words2 ys where (y,ys) = break2 onSpace xs
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...