问题
我有[123,123]的int列表,我需要作为[1,2,3,1,2,3]
当前代码
我使用递归
尝试了以下代码fat::[Int]->[Int]
fat [] = []
fat (a,b,c:xs) = a : b : c : fat xs
结论
我不知道如何在列表[123,123] separetly中将值设为'1','2,'3
答案 0 :(得分:5)
我建议在列表的每个元素上使用this answer中给出的digs
函数。它将Int
拆分为数字列表([Int]
)。然后你只需要连接结果列表。对于concatMap
fat :: [Int] -> [Int]
fat = concatMap digs
这给出了:
*Main> fat [123,123]
[1,2,3,1,2,3]
如果我理解正确,你想要的是什么。
答案 1 :(得分:3)
splitNum :: Int -> [Int]
splitNum n | n <= 9 = [n]
| otherwise = (splitNum (n `div` 10)) ++ [n `mod` 10]
fat :: [Int] -> [Int]
fat x = concatMap splitNum x
splitNum用于将Int转换为[Int],方法是将其拆分为十个提醒并将生成的Int附加到拆分的休息(递归!)
现在,拥有一个将数字转换为列表的函数,通过输入,将splitNum应用于内部列表中的任何数字,并连接所有结果列表(列表理解!)
答案 2 :(得分:2)
作为一名新的Haskell程序员,我会告诉你我对这个问题的看法。仅仅因为我认为有很多选择是好的,特别是来自不同经验的人。
以下是我对这个问题的看法:
澄清:
util函数看起来像这样:
import Char
charsToInts :: [Char] -> [Int]
charsToInts [] = []
charsToInts (x:xs) = digitToInt x : charsToInts xs
来自迫切的背景,这就是我将如何解决它。可能比仅仅以数学方式分割数字要慢,但我认为展示替代方案会很有趣。
答案 3 :(得分:2)
要直截了当地查明问题,您不知道如何分别访问数字,因为您不了解Haskell类型和模式匹配。让我试着帮助消除你的一些误解。
让我们看看你的清单:
[123, 123]
它的类型是什么?它显然是一个整数列表,或[Int]
。使用列表,您可以在构造函数:
上模式匹配,将lispers称为“cons”或“list constructor”。您在:
的左侧放置了一个元素,在右侧放置了另一个列表。右侧的列表可以是空列表[]
,它基本上表示列表的结尾。 Haskell提供了“语法糖”,使列表更容易编写,但[123,456]
实际上已经被123:(456:[])
所取代。因此,当您模拟匹配(x:y:z)
时,您现在可以看到x
将被分配123
并且y
将被分配456
。在z
和x
之后,y
将成为列表的其余部分;在这种情况下,只剩下[]
。
现在,与:
匹配的模式适用于列表。 Int
不是列表,因此您无法使用:
对Int
的数字进行模式匹配。但是,String
s 是列表,因为String
与[Char]
相同。因此,如果您将Int
变为String
,则可以模式匹配每个字符。
map show [123, 123]
map
将函数应用于列表的所有元素。 show
可以Int
并将其转换为String
。因此,我们map show
在Int
列表上获取String
的列表。
["123", "123"]
现在让我们将Strings
转换为Int
的列表。由于String
只是[Char]
,我们将再次使用map
。
map digitToInt "123" -- this requires that you import Data.Char (digitToInt)
这会给我们[1,2,3]
;列表中的每个Char
都会变成Int
。这是我们想要对列表String
中的每个["123", "123"]
执行的操作。我们想要map digitToInt
到每个String。但是我们有一个String
的列表。那么我们该怎么办?我们映射它!
map (map digitToInt) ["123", "123"]
这会给我们[[1,2,3], [1,2,3]]
。几乎是我们想要的。现在,我们只需将Int
([[Int]]
)列表的列表展平为Int
([Int]
)列表。我们怎么做?停止...... Hoogle时间! Hoogling [[a]] - &gt; [a]我们发现第一个命中,concat
,正是我们想要的。
让我们把它们放在一起。首先,我们map show
从[Int]
转到[String]
。然后,我们map (map digitToInt)
从[String]
转到[[Int]]
。然后,我们concat
从[[Int]]
转到[Int]
。然后我们只会print
出来!
import Data.Char (digitToInt)
main = print $ concat $ map (map digitToInt) $ map show $ [123, 123]
现在让我们把大部分内容放到函数fat
import Data.Char (digitToInt)
main = print $ fat [123, 123]
fat :: [Int] -> [Int]
fat xs = concat $ map (map digitToInt) $ map show $ xs
从这里你可以通过几种不同的方式让它变得更漂亮。 concat $ map
与concatMap
相同,由于我们按顺序映射(map digitToInt)
和show
,我们可以合并它们。同样让它变得无意义,我们最终可以得到一个非常简洁的定义:
fat = concatMap (map digitToInt . show)
答案 4 :(得分:1)
为了完整起见,我按照@Ancide
的建议写了它<强>实施强>
fat' :: [Int] -> [Int]
fat' l = map (read) [[z] | z <- [x | k <- (map (show) l), x <- k]]
<强>解释强>:
{ - last result - } 代表最后一段代码的结果。
map (show) l
这会占用 l 中的每个元素并将其转换为 [String] 。
[x | k <- {- last result -}, x <- k]
当 k 遍历最后结果中的所有元素时, x 枚举每个 k 中的所有字符。所有这些都被添加到列表中。现在你有一个 String ,分别是一个 [Char] ,其中所有数字都是彼此相邻的。
[[z] | z <- {- last result -}]
此部分从 String 中获取每个 Char ,并将其放入空的 String 中。注意 [z] 部分!这会在 z 周围创建一个列表,它(见上文)与 String 相同。现在,您有一个 String 列表,每个数字都带有 String 。
map (read) {- last result -}
这将获取最后结果中的每个项目,并将其转换回 Int 并将它们连接到 [Int] 。现在,您有一个所需结果的 [Int] 类型列表。
<强>恢复强>
虽然这种实现是可行的,但由于所有的类型转换,它既不快,也不可读。
答案 5 :(得分:1)
使用列表monad,我想出了这个。几乎与@ Ankur的解决方案相同,除了使用列表monad:
fat :: [Int] -> [Int]
fat is = is >>= show >>= return . digitToInt
答案 6 :(得分:0)
如果你有两个号码a
和b
,那么你可以通过10 * a + b将它们变成一个数字。同样的原则适用于三个。
听起来这样做的一种方法是将splitEvery分成三个块,然后map
一个函数将三个列表转换为一个数字。
这有帮助吗?
答案 7 :(得分:0)
你需要一个函数将Integer转换为string ...这显然是Show函数 另一个将Char转换为Integer的函数,即模块Char
中的“digitToInt”我们走了:
fat::[Int]->[Int]
fat [] = []
fat ls = concat $ map (map digitToInt) (map show ls)
如果有效,请告诉我。)