Один из способов сделать это - применить group
к каждой строке:
> group "hhhh"
["hhhh"]
> group "plml"
["p","l","m","l"]
Затем, если вы takeWhile
число групп равно 1, вы получите все однородные строки:
> test = ["hello","help","hell","helm"]
> import Data.List
> takeWhile ((==1) . length) . map group . transpose $ test
[["hhhh"],["eeee"],["llll"]]
Вы можете избавиться от лишнего слоя списка с помощью map head
.
Кроме того, было бы лучше заменить этот тест для отдельных групп пользовательской функцией сопоставления с шаблоном:
single :: [a] -> Bool
single [a] = True
single _ = False
и используйте:
> map head . takeWhile single . map group . transpose $ test
["hhhh","eeee","llll"]]
Основное отличие состоит в том, что (==1) . length
необходимо оценить и подсчитать длину всего набора групп, но single
может остановиться раньше. Например, на бесконечной строке:
> ((==1) . length) $ group $ "aaa" ++ repeat 'b' -- hangs forever
> single $ group $ "aaa" ++ repeat 'b' -- returns `False` at first 'b'
Альтернативой, предложенной в комментариях, была бы более прямая проверка того, что первый символ равен всем остальным символам:
allSame :: (Eq a) => [a] -> Bool
allSame (x:rest) = all (==x) rest
и:
> takeWhile allSame . transpose $ test
["hhhh","eeee","llll"]
СПОЙЛЕРЫ: Согласно вашим комментариям, вы пытаетесь найти самый длинный префикс, поэтому в завершение обратите внимание, что вы хотите map head
по:
["hhhh","eeee","llll"]
получить:
['h','e','l']
что то же самое, что:
"hel"
Поскольку map head
, за которым следует map head
, можно записать map head . map head
или даже короче map (head . head)
, окончательное определение с использованием group
может быть записано:
prefix :: (Eq a) => [[a]] -> [a]
prefix = map (head . head) . takeWhile single . map group . transpose
where single [a] = True
single _ = False
и окончательное определение с использованием allSame
можно записать:
prefix :: (Eq a) => [[a]] -> [a]
prefix = map head . takeWhile allSame . transpose
where allSame (x:rest) = all (==x) rest
person
K. A. Buhr
schedule
10.12.2019
takeWhile ((==1) . length . nub)
. Извините за краткий комментарий, я на лекции;) - person MikaelF   schedule 10.12.2019nub
излишне дорого стоит, если все, что вам нужно знать, это то, что есть ровно один элемент. Вместо этого вы можете использоватьall
, чтобы проверить, равен ли каждый элемент списка первому элементу списка. - person amalloy   schedule 10.12.2019