#list #haskell #recursion #guard
#Список #haskell #рекурсия #охранник
Вопрос:
Я новичок в Haskell и пытаюсь понять, как написать код, который отбрасывает все нули до тех пор, пока элемент списка не станет> 0.
Так , например:
Входные данные: [0,0,5,6,0]
Вывод: [5,6,0]
До сих пор я писал это:
zeroUntil :: [Int] -> [Int]
zeroUntil [] = []
zeroUntil (x:xs)
| x == 0 = drop x (xs)
| otherwise = zeroUntil xs
Но каким-то образом вместо [5,6,0] я получаю [ ] .
Может кто-нибудь, пожалуйста, объяснить, что я сделал не так?
Комментарии:
1. Ваша реализация не соответствует вашему результату. При запуске на входе , который вы описываете, он не выдает
[]
, а наоборот[0,5,6,0]
. Конечно, все еще неправильно: он реализует совершенно иную функцию, чем вы предполагаете. Но, пожалуйста, убедитесь, что ваши проблемы воспроизводимы, вставив ваш фактический код и выходные данные и дважды проверив их перед публикацией.
Ответ №1:
Вы можете использовать dropWhile :: (a -> Bool) -> [a] -> [a]
и, таким образом, удалять элементы, если они являются нулями:
zeroUntil :: [Int] -> [Int]
zeroUntil = dropWhile (0 ==)
Если вы хотите отбрасывать нули до тех пор, пока элемент не станет больше нуля, вы можете использовать рекурсию. Здесь ваш рекурсивный случай должен давать элементы, если они меньше нуля:
zeroUntil :: [Int] -> [Int]
zeroUntil [] = []
zeroUntil (0:xs) = zeroUntil xs
zeroUntil (x:xs)
| x > 0 = x : xs -- ← end of recursion, return the list
| otherwise = x : zeroUntil xs -- ← yield x and recurse
например:
Prelude> zeroUntil [0,0,5,6,0]
[5,6,0]
Prelude> zeroUntil [0,-1,5,6,0]
[-1,5,6,0]
Ответ №2:
zeroUntil :: [Int] -> [Int]
zeroUntil [] = []
zeroUntil (x:xs)
| x == 0 = drop x (xs)
| otherwise = [x] (zeroUntil xs)
Вы должны добавить первый элемент ( x
) в список, возвращаемый рекурсивным вызовом, в противном случае вы возвращаете пустой список.