Converting a list of integers to one Int (like concat) in haskell

Pretty much what the title says. I have a list of integers: [1,2,3]. I want to change this to Integer 123. My first thought was concat, but it does not work because it is the wrong type, I tried different things, but usually I just return the same list. Any help was greatly appreciated.

Also, I had found a way to print the correct thing (putStr), except that I want the type to be Integer, and putStr does not.

+8
list integer haskell
source share
8 answers

You can use foldl to combine all the elements of a list:

 fromDigits = foldl addDigit 0 where addDigit num d = 10*num + d 

The addDigit function addDigit called by foldl to add numbers one by one, starting from the leftmost one.

 *Main> fromDigits [1,2,3] 123 

Edit:
foldl scans the list from left to right, adding items to accumulate some value.

The second argument to foldl , 0 in this case is the starting value of the process. At the first stage, this initial value is combined with 1 , the first element of the list, by calling addDigit 0 1 . This leads to 10 * 0 + 1 = 1. In the next step, this 1 is combined with the second element of the list, on addDigit 1 2 , giving 10 * 1 + 2 = 12. Then it is combined with the third element of the list, addDigit 12 3 , as a result get 10 * 12 + 3 = 123.

Thus, meaningless multiplication by zero is only the first step; in the next steps, multiplication is really necessary to add new digits "to the end" of the number that will accumulate.

+23
source share

You could concat represent strings of numbers and then read them back, for example:

 joiner :: [Integer] -> Integer joiner = read . concatMap show 
+11
source share

It worked very well for me.

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

How a function reads:
Step 1 - convert each int in the list to a string (map show (x:xs))
Step 2 - (concat (step 1)) each of these lines together (concat (step 1))
Step 3 - read the line as type read (step 2) :: Int type int read (step 2) :: Int

+3
source share

Use read as well as intToDigit :

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

Has the advantage (or disadvantage) of puking on multi-digit numbers.

+2
source share

Another idea: to say that the last digit is calculated for 1, and the next digit is 10, the digit is up to 100, etc. Therefore, to convert a list of numbers to a number, you need to cancel it (to start from the back), multiply the numbers along with the corresponding powers of ten and add the result together.

To cancel the list, use reverse to get ten values, you can use iterate (*10) 1 (try in GHCi or Hugs!) To multiply the corresponding numbers in two lists, use zipWith (*) and add everything together, use sum - it really helps to know some library functions! By connecting a bit together, you get

 fromDigits xs = sum (zipWith (*) (reverse xs) (iterate (*10) 1)) 

Evaluation Example:

 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 

However, this solution is slower than those with foldl due to the reverse call, and since you are building these ten powers to use them again directly. On the plus side, this way of constructing numbers is closer to how people usually think (at least I do!), While foldl connections essentially use the Horner Rule .

+1
source share

How to print a number, not

 putStr n 

just try

 putStr (show n) 

The rationale is that putStr can only print lines. Therefore, you need to convert the number to a string before passing it.

You can also try using the print function from Prelude. This can print anything that is "exponential" (any instance of the Show class), and not just strings. But keep in mind that print n matches (roughly) putStrLn (show n) , not putStr (show n) .

0
source share

You can also use zip , fodlr and endless lists:

 toInt :: [Int] -> Int toInt [] = error "Empty list" toInt xs = foldr (\(t,x) folded -> t*x+folded) 0 zipped where zipped = zip (map (\x -> 10^x) [0..]) (reverse xs) 

But there are much more elegant solutions (see above). This is just to give one more option.

0
source share

I am not an expert at Haskell, but this is the easiest way I can come up with to solve this problem, which does not involve the use of any other external functions.

 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) 

As you can see, I assumed that you are trying to make a list of numbers. If for some reason this is not your case, I am sure it will not work. :(

In my solution, first of all, I defined a function called reverseDigits that reverses the original list. For example, [1,2,3] - [3,2,1]

After that, I use the concatReversed function concatReversed which takes a list of digits and the number d, which is the result of a tenfold increase in the first digit at the position of the list. If the list is empty, it returns 0, and if not, it returns the first digit in the list times d, plus a call to concatReversed passing the rest of the list, and d times 10.

Hope the code speaks for itself, because I think my poor English explanation didn't help much.


edit

After a long time, I see that my decision is very dirty, as it requires turning the list so that you can multiply each digit by 10 and increase the index of the digit in the list from right to left. Now, knowing the tuples, I see that a much better approach is to have a function that receives both the accumulated converted part and the rest of the list, so with each call, the function multiplies the accumulated part by 10, and then adds the current digit.

 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)) 
-2
source share

All Articles