Haskell Int的列表:[123]至[1,2,3]

时间:2011-06-10 10:18:28

标签: list haskell

问题

我有[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

8 个答案:

答案 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程序员,我会告诉你我对这个问题的看法。仅仅因为我认为有很多选择是好的,特别是来自不同经验的人。

以下是我对这个问题的看法:

  • 对于列表中的每个项目,使用read将该项目转换为char列表。
  • 将该char列表发送到一个函数中,该函数将该列表的每个项目转换为int,然后返回一个int列表。
  • Concat将列表列入主列表。

澄清:

  • [123,234]
  • 123变成['1','2','3']
  • ['1','2','3']变成[1,2,3]
  • [1,2,3]在主列表
  • 中获得连续
  • 循环重复为234.

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。在zx之后,y将成为列表的其余部分;在这种情况下,只剩下[]

现在,与:匹配的模式适用于列表Int不是列表,因此您无法使用:Int的数字进行模式匹配。但是,String s 列表,因为String[Char]相同。因此,如果您将Int变为String,则可以模式匹配每个字符。

map show [123, 123]

map将函数应用于列表的所有元素。 show可以Int并将其转换为String。因此,我们map showInt列表上获取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 $ mapconcatMap相同,由于我们按顺序映射(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)

如果你有两个号码ab,那么你可以通过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)

如果有效,请告诉我。)