Как разбить число на список цифр? [Дубликат]

Поскольку он возвращает кортежи (и может использовать тонны памяти), трюк zip(*zipped) кажется мне более умным, чем полезным.

Вот функция, которая на самом деле даст вам обратный zip.

def unzip(zipped):
    """Inverse of built-in zip function.
    Args:
        zipped: a list of tuples

    Returns:
        a tuple of lists

    Example:
        a = [1, 2, 3]
        b = [4, 5, 6]
        zipped = list(zip(a, b))

        assert zipped == [(1, 4), (2, 5), (3, 6)]

        unzipped = unzip(zipped)

        assert unzipped == ([1, 2, 3], [4, 5, 6])

    """

    unzipped = ()
    if len(zipped) == 0:
        return unzipped

    dim = len(zipped[0])

    for i in range(dim):
        unzipped = unzipped + ([tup[i] for tup in zipped], )

    return unzipped
30
задан Greg B 18 October 2010 в 22:04
поделиться

15 ответов

Слышали ли вы о div и mod ?

Вы, вероятно, захотите изменить список чисел, если хотите сначала обработать наиболее значительную цифру.

135 `div` 10 = 13
135 `mod` 10 = 5

Обобщение числа в строку:

digs :: Integral x => x -> [x]
digs 0 = []
digs x = digs (x `div` 10) ++ [x `mod` 10]

Или наоборот:

digs :: Integral x => x -> [x]
digs 0 = []
digs x = x `mod` 10 : digs (x `div` 10)

Это относится к 0 как к отсутствию цифр. Простая функция обертки может иметь дело с этим специальным случаем, если вы хотите.

Обратите внимание, что это решение не работает для отрицательных чисел (вход x должен быть целым, т. Е. Целое число).

70
ответ дан David Cain 21 August 2018 в 01:29
поделиться
  • 1
    Позаботьтесь, чтобы привести пример? – Greg B 18 October 2010 в 22:01
  • 2
  • 3
    Я добавил пример к моему коду, так как не вижу, как div и mod помогут мне пройти по цифрам любого произвольного числа. Не могли бы вы рассказать о своих мыслях. – Greg B 18 October 2010 в 22:05
  • 4
    @Greg B это исходный код haskell, который делает то же самое, что и ваш алгоритм, но используя @supercooldave algorithm = & gt; pastie.org/1231091 – Roman Gonzalez 18 October 2010 в 22:37
  • 5
    yes digs 0 должно быть [0]. – MySchizoBuddy 24 November 2014 в 21:53

Через понимание списка:

import Data.Char

digits :: Integer -> [Integer]
digits n = [toInteger (digitToInt x) | x <- show n]

вывод:

> digits 1234567890
[1,2,3,4,5,6,7,8,9,0]
1
ответ дан Andrey 21 August 2018 в 01:29
поделиться

Используя тот же метод, который используется в вашем сообщении, вы можете сделать:

digits :: Integer -> [Int]
digits n = map (\x -> read [x] :: Int) (show n)

См. его в действии:

Prelude> digits 123
[1,2,3]

Помогает ли это?

10
ответ дан Daniel 21 August 2018 в 01:29
поделиться

Для возврата списка [Integer]

import Data.Char
toDigits :: Integer -> [Integer]
toDigits n = map (\x -> toInteger (digitToInt x)) (show n)
0
ответ дан Duda Dornelles 21 August 2018 в 01:29
поделиться
  • 1
    Или в свободном стиле, это будет: toDigits = map (toInteger . digitToInt) . show – kibin 16 August 2015 в 17:20

Вот улучшение ответа выше. Это позволяет избежать дополнительных 0 в начале (Примеры: [0,1,0] для 10, [0,1] для 1). Используйте совпадение шаблонов для обработки случаев, когда x & lt; 10 по-разному:

toDigits :: Integer -> [Integer] -- 12 -> [1,2], 0 -> [0], 10 -> [1,0]
toDigits x
    | x < 10 = [x]
    | otherwise = toDigits (div x 10) ++ [mod x 10]

Я бы поставил это в ответ на этот ответ, но у меня нет необходимых точек репутации: (

1
ответ дан granmoe 21 August 2018 в 01:29
поделиться

Вы также можете просто повторно использовать digits из Hackage.

12
ответ дан hammar 21 August 2018 в 01:29
поделиться

Учебник разворачивается

import qualified Data.List as L
digits = reverse . L.unfoldr (\x -> if x == 0 then Nothing else Just (mod x 10, div x 10))
9
ответ дан jon_darkstar 21 August 2018 в 01:29
поделиться
  • 1
    Очевидно, это способ сделать. Если вы включите import Data.Bool.bool, вы можете сделать его еще более сексуальным, как unfoldr (\x -> bool Nothing (Just (rem x 10, div x 10)) (x > 0)) – Redu 12 October 2017 в 15:34
  • 2
    Вариант, который работает с отрицательными номерами: digits d = reverse . unfoldr (\x -> bool (Just $ swap $ divMod x 10) Nothing (x == 0)) $ abs d. Необходимые импорт: Data.List (unfoldr), Data.Tuple (swap), Data.Bool (bool) – Matthias Braun 13 March 2018 в 21:04

Вы можете использовать

digits = map (`mod` 10) . reverse . takeWhile (> 0) . iterate (`div` 10)

или для обратного порядка

rev_digits = map (`mod` 10) . takeWhile (> 0) . iterate (`div` 10)

Итерационная часть генерирует бесконечный список, делящий аргумент на каждом шаге на 10, поэтому 12345 становится [ 12345,1234,123,12,1,0,0 ..]. При этом часть занимает только интересную непустую часть списка. Затем мы отменим (если хотим) и возьмем последнюю цифру каждого номера списка.

Здесь я использовал стиль без точек, поэтому вы можете представить невидимый аргумент n по обе стороны от " уравнение". Однако, если вы хотите записать его таким образом, вы должны подставить верхний уровень . на $:

digits n = map(`mod` 10) $ reverse $ takeWhile (> 0) $ iterate (`div`10) n
9
ответ дан Landei 21 August 2018 в 01:29
поделиться

Принятый ответ правильный, за исключением того, что он выдает пустой список, когда ввод равен 0, однако я считаю, что вывод должен быть [0], когда ввод равен нулю.

И я не думаю, что это касается случая, когда ввод отрицательный. Ниже приведена моя реализация, которая решает две вышеуказанные проблемы.

toDigits :: Integer -> [Integer]
toDigits n
 | n >=0 && n < 10 = [n]
 | n >= 10 = toDigits (n`div`10) ++ [n`mod`10]
 | otherwise = error "make sure your input is greater than 0" 
0
ответ дан Leonard Ge 21 August 2018 в 01:29
поделиться
digits = reverse . unfoldr go
  where go = uncurry (*>) . (&&&) (guard . (>0)) (Just . swap . (`quotRem` 10))
-2
ответ дан Li Chanjuan 21 August 2018 в 01:29
поделиться
  • 1
    Этот ответ будет значительно улучшен с объяснением – Sam P 1 May 2016 в 19:43
  • 2
    quotRem разделяет последнюю цифру в основном и возвращает кортеж цифры и остальных. – Blank Chisui 2 November 2017 в 16:28

Принятый ответ велик, но не работает в случае отрицательных чисел, так как mod (-1) 10 оценивается до 9. Если вы хотите, чтобы это правильно обрабатывало отрицательные числа ... это может быть не так, если это допустит следующий код.

digs :: Int -> [Int]
digs 0 = []
digs x
  | x < 0 = digs ((-1) * x)
  | x > 0 = digs (div x 10) ++ [mod x 10]
1
ответ дан mschuett 21 August 2018 в 01:29
поделиться
  • 1
    Не могли бы вы реорганизовать это с помощью abs? – Raman Shah 13 June 2017 в 12:51
digits :: Integer -> [Int]
digits = map (read . (:[])) . show

, или вы можете вернуть его в []:

digits :: Integer -> [Int]
digits = map (read . return) . show

или, с Data.Char.digitToInt:

digits :: Integer -> [Int]
digits = map digitToInt . show

так же, как на самом деле Daniel , но бессмысленно и использует Int, потому что цифра не должна превышать maxBound :: Int.

17
ответ дан muhmuhten 21 August 2018 в 01:29
поделиться
  • 1
    возможно (цифры = карта (read. return). show)? или (читай).) – Ed'ka 19 October 2010 в 21:36
  • 2
    версия digitToInt, вероятно, все равно лучше, а :[] для меня несколько более очевидна. э-э, я отредактирую его. Я понятия не имею, откуда чист. – muhmuhten 19 October 2010 в 23:00
  • 3
    перечитайте это, на этот раз, признав pure и да, это будет эквивалентно. (требуется эквивалент.) – muhmuhten 18 August 2014 в 01:27
  • 4
    можете ли вы объяснить, что такое «период»? между чтением и возвратом – MySchizoBuddy 22 November 2014 в 17:28
  • 5
    функциональный состав. (.) :: (b -> c) -> (a -> b) -> a -> c – muhmuhten 23 November 2014 в 01:37

Аппликативный . Pointfree . Оригами . Аккуратно.

Наслаждайтесь:

import Data.List                                                                
import Data.Tuple                                                               
import Data.Bool                                                                
import Control.Applicative 

digits = unfoldr $ liftA2 (bool Nothing) (Just . swap . (`divMod` 10)) (> 0) 
1
ответ дан Scarabyte 21 August 2018 в 01:29
поделиться

Я пытался сохранить хвостовую рекурсию

toDigits :: Integer -> [Integer]
toDigits x = reverse $ toDigitsRev x

toDigitsRev :: Integer -> [Integer]
toDigitsRev x
    | x <= 0 = []
    | otherwise = x `rem` 10 : toDigitsRev (x `quot` 10)
0
ответ дан Wessel Badenhorst 21 August 2018 в 01:29
поделиться
  • 1
    Это не хвостовая рекурсия - в последней ветке есть минус, кроме рекурсивного вызова. – Tamoghna Chowdhury 27 June 2017 в 18:04
  • 2
    Это не хвостовая рекурсия - в последней ветке есть минус, кроме рекурсивного вызова. – Tamoghna Chowdhury 27 June 2017 в 18:04
0
ответ дан Wojciech Danilo 31 October 2018 в 20:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: