将整数列表转换为haskell中的一个Int(如concat)

时间:2009-12-16 23:13:11

标签: list haskell integer

相当于标题所说的内容。我有一个整数列表,如下所示:[1,2,3]。我想把它改成整数123.我的第一个想法是concat但是这不起作用,因为它是错误的类型,我尝试了各种各样的东西,但通常我最终返回相同的列表。非常感谢任何帮助。

此外我找到了一种方法来打印正确的东西(putStr),除了我希望类型为Integer而putStr不这样做。

8 个答案:

答案 0 :(得分:23)

您可以使用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,得到10 * 1 + 2 = 12.然后将其与第三个组合列表的元素,addDigit 12 3,导致10 * 12 + 3 = 123。

毫无意义地乘以零只是第一步,在接下来的步骤中,实际上需要乘法来将新数字添加到累计数字的“结尾”。

答案 1 :(得分:11)

您可以concat数字的字符串表示形式,然后read返回,如下所示:

joiner :: [Integer] -> Integer
joiner = read . concatMap show

答案 2 :(得分:3)

这对我来说非常好。

read (concat (map show (x:xs))) :: Int

函数如何读取:
第1步 - 将列表中的每个int转换为字符串 (map show (x:xs))
第2步 - 将每个字符串组合在一起 (concat (step 1))
第3步 - 读取字符串作为int的类型 read (step 2) :: Int

答案 3 :(得分:2)

使用readintToDigit

joinInt :: [Int] -> Int
joinInt l = read $ map intToDigit l

具有多位数字的优势(或劣势)。

答案 4 :(得分:1)

另一个想法是说:最后一位数为1,倒数第二位数为10,前一位数为100,等等。因此,要将数字列表转换为数字,您需要将其反转(以便从后面开始),将数字与相应的10的幂相乘,并将结果相加。

要反转列表,请使用reverse来获取10的幂,您可以使用iterate (*10) 1(在GHCi或Hugs中尝试!),将两个列表的相应数字相乘{{1并将所有内容添加到一起,使用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并且因为你正在构建那些10的幂而只是再次直接使用它们。从好的方面来说,这种建立数字的方式更接近人们通常的想法(至少我这样做!),而reverse - 解决方案本质上使用Horner's rule

答案 5 :(得分:0)

至于如何打印数字,而不是

putStr n

试试

putStr (show n)

原因是putStr只能打印字符串。所以你需要在传入之前将数字转换为字符串。

您可能还想尝试Prelude的print功能。这个可以打印任何“可显示的”(类Show的任何实例),而不仅仅是字符串。但请注意,print n(大致)与putStrLn (show n)相对应,而不是putStr (show n)

答案 6 :(得分:0)

join :: Integral a => [a] -> a
join [x] = x
join (x:xs) = (x * (10 ^ long)) + join(xs)
    where long = length(x:xs)

我们可以定义一个名为join的函数,给定一个整数列表,它可以返回另一个整数。我们正在使用递归将给定列表的标题与列表的其余部分分开,并使用模式匹配来定义边缘条件,以便递归可以结束。

答案 7 :(得分:-2)

我不是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。

希望代码能说明问题,因为我认为我糟糕的英语解释并不是很有帮助。