В значительной степени, что говорит заголовок. У меня есть список Целых чисел как так: [1,2,3]. Я хочу изменить это в на Целое число 123. Моя первая мысль была concat, но это не работает, потому что это имеет неправильный тип, я попробовал различные вещи, но обычно я только заканчиваю тем, что возвратил тот же список. Любая справка значительно ценится.
Также я нашел способ распечатать правильную вещь (putStr) кроме, я хочу, чтобы тип был Целым числом, и putStr не делает этого.
Вы можете использовать foldl
для объединения всех элементов списка:
fromDigits = foldl addDigit 0
where addDigit num d = 10*num + d
Функция addDigit
вызывается foldl
для добавления цифр одну за другой, начиная с самой левой.
*Main> fromDigits [1,2,3]
123
Изменить:
foldl
проходит через список слева направо, добавляя элементы для накопления некоторого значения.
Второй аргумент foldl
, 0
в данном случае является начальным значением процесса. На первом шаге это начальное значение комбинируется с 1
, первым элементом списка, путем вызова addDigit 0 1
. В результате получается 10 * 0 + 1 = 1. На следующем этапе эта 1 объединяется со вторым элементом списка addDigit 1 2
,
You could concat
the string representations of the numbers, and then read
them back, like so:
joiner :: [Integer] -> Integer
joiner = read . concatMap show
Use read
and also intToDigit
:
joinInt :: [Int] -> Int
joinInt l = read $ map intToDigit l
Has the advantage (or disadvantage) of puking on multi-digit numbers.
Что касается того, как печатать число, вместо
putStr n
попробуйте
putStr (show n)
Причина в том, что putStr
может печатать только строки. Поэтому вам нужно преобразовать число в строку перед его передачей.
Вы также можете попробовать функцию print
из Prelude. Он может печатать все, что "показывается" (любой экземпляр класса Show
), а не только строки. Но имейте в виду, что print n
соответствует (примерно) putStrLn (show n)
, а не putStr (show n)
.
Я не эксперт в Haskell, но это самый простой способ, который я могу придумать для решения этой проблемы, не требующий использования каких-либо других внешних функций.
concatDigits :: [Int] -> Int
concatDigits [] = 0
concatDigits xs = concatReversed (reverseDigits xs) 1
reverseDigits :: [Int] -> [Int]
reverseDigits [] = []
reverseDigits (x:xs) = (reverseDigits xs) ++ [x]
concatReversed :: [Int] -> Int -> Int
concatReversed [] d = 0
concatReversed (x:xs) d = (x*d) + concatReversed xs (d*10)
Как видите, я предположил, что вы пытаетесь объединить список цифр. Если случайно это не ваш случай, я почти уверен, что это не сработает. : (
В моем решении, прежде всего, я определил функцию с именем reverseDigits
, которая меняет исходный список на противоположный. Например, с [1,2,3] на [3,2,1]
После этого я использую функцию concatReversed
, которая принимает список цифр и число d, которое является результатом десятичного увеличения первой цифры в позиции списка. Если список пуст, он возвращает 0 , а если нет, возвращает первую цифру в списке, умноженную на d, плюс вызов concatReversed
с передачей остальной части списка и d умножением на 10.
Надеюсь, что код говорит сам за себя, потому что я думаю, что мое плохое объяснение на английском не очень помогло.
Спустя долгое время я вижу, что мое решение очень запутанное, так как оно требует перевернуть список, чтобы иметь возможность умножать каждую цифру на 10-кратную величину индекса цифры в списке, справа налево. Теперь, зная кортежи, я вижу, что гораздо лучший подход - иметь функцию, которая получает как накопленную преобразованную часть, так и оставшуюся часть списка, поэтому при каждом вызове в in умножает накопленную часть на 10, а затем добавляет текущую цифру.
concatDigits :: [Int] -> Int
concatDigits xs = aggregate (xs, 0)
where aggregate :: ([Int], Int) -> Int
aggregate ([], acc) = acc
aggregate (x:xs, acc) = aggregate (xs, (acc * 10 + x))
Другая идея - сказать: последняя цифра считается за 1, предпоследняя - за 10, цифра перед ней - за 100. и т. д. Итак, чтобы преобразовать список цифр в число, вам нужно перевернуть его (чтобы начать с конца), умножить цифры вместе с соответствующими степенями десяти и сложить результат вместе.
Чтобы перевернуть список , используйте обратный
, чтобы получить степень десяти, вы можете использовать iterate (* 10) 1
(попробуйте в GHCi или Hugs!), для умножения соответствующих цифр двух списков используйте zipWith (*)
и чтобы сложить все вместе, используйте sum
- это действительно помогает знать несколько библиотечных функций! Сложив биты вместе, вы получите
fromDigits xs = sum (zipWith (*) (reverse xs) (iterate (*10) 1))
Пример оценки:
fromDigits [1,2,3,4]
==> sum (zipWith (*) (reverse [1,2,3,4]) [1,10,100,1000, ....]
==> sum (zipWith (*) [4,3,2,1] [1,10,100,1000, ....])
==> sum [4 * 1, 3 * 10, 2 * 100, 1 * 1000]
==> 4 + 30 + 200 + 1000
==> 1234
Однако это решение работает медленнее, чем решения с foldl
, из-за вызова reverse
и поскольку вы наращиваем эти силы десяти только для того, чтобы снова использовать их напрямую. С другой стороны, этот способ построения чисел ближе к тому, как люди обычно думают (по крайней мере, я!), В то время как foldl
-решения, по сути, используют правило Хорнера . 1118512] для умножения соответствующих цифр двух списков используйте zipWith (*)
, а чтобы сложить все вместе, используйте sum
- это действительно помогает знать несколько библиотечных функций! Сложив биты вместе, вы получите
fromDigits xs = sum (zipWith (*) (reverse xs) (iterate (*10) 1))
Пример оценки:
fromDigits [1,2,3,4]
==> sum (zipWith (*) (reverse [1,2,3,4]) [1,10,100,1000, ....]
==> sum (zipWith (*) [4,3,2,1] [1,10,100,1000, ....])
==> sum [4 * 1, 3 * 10, 2 * 100, 1 * 1000]
==> 4 + 30 + 200 + 1000
==> 1234
Однако это решение медленнее, чем решения с foldl
, из-за вызова reverse
и поскольку вы наращиваем эти силы десяти только для того, чтобы снова использовать их напрямую. С другой стороны, этот способ построения чисел ближе к тому, как люди обычно думают (по крайней мере, я!), В то время как foldl
-решения, по сути, используют правило Хорнера . 1118512] для умножения соответствующих цифр двух списков используйте zipWith (*)
, а чтобы сложить все вместе, используйте sum
- это действительно помогает знать несколько библиотечных функций! Сложив биты вместе, вы получите
fromDigits xs = sum (zipWith (*) (reverse xs) (iterate (*10) 1))
Пример оценки:
fromDigits [1,2,3,4]
==> sum (zipWith (*) (reverse [1,2,3,4]) [1,10,100,1000, ....]
==> sum (zipWith (*) [4,3,2,1] [1,10,100,1000, ....])
==> sum [4 * 1, 3 * 10, 2 * 100, 1 * 1000]
==> 4 + 30 + 200 + 1000
==> 1234
Однако это решение работает медленнее, чем решения с foldl
, из-за вызова reverse
и поскольку вы наращиваем эти силы десяти только для того, чтобы снова использовать их напрямую. С другой стороны, этот способ построения чисел ближе к тому, как люди обычно думают (по крайней мере, я!), В то время как foldl
-решения, по сути, используют правило Хорнера . 1118512] вы получите
fromDigits xs = sum (zipWith (*) (reverse xs) (iterate (*10) 1))
Пример оценки:
fromDigits [1,2,3,4]
==> sum (zipWith (*) (reverse [1,2,3,4]) [1,10,100,1000, ....]
==> sum (zipWith (*) [4,3,2,1] [1,10,100,1000, ....])
==> sum [4 * 1, 3 * 10, 2 * 100, 1 * 1000]
==> 4 + 30 + 200 + 1000
==> 1234
Однако это решение медленнее, чем решения с foldl
, из-за вызова reverse
и поскольку вы наращиваете те степени десяти только для того, чтобы использовать их напрямую снова. С другой стороны, этот способ построения чисел ближе к тому, как люди обычно думают (по крайней мере, я!), В то время как foldl
-решения, по сути, используют правило Хорнера . 1118512] вы получите
fromDigits xs = sum (zipWith (*) (reverse xs) (iterate (*10) 1))
Пример оценки:
fromDigits [1,2,3,4]
==> sum (zipWith (*) (reverse [1,2,3,4]) [1,10,100,1000, ....]
==> sum (zipWith (*) [4,3,2,1] [1,10,100,1000, ....])
==> sum [4 * 1, 3 * 10, 2 * 100, 1 * 1000]
==> 4 + 30 + 200 + 1000
==> 1234
Однако это решение медленнее, чем решения с foldl
, из-за вызова reverse
и поскольку вы наращиваете те степени десяти только для того, чтобы использовать их напрямую снова. С другой стороны, этот способ построения чисел ближе к тому, как люди обычно думают (по крайней мере, я!), В то время как foldl
-решения, по сути, используют правило Хорнера . 1118512]