Haskell整数列表[5,5,5] - > [555]没有Data.Lists.Split

时间:2011-06-10 18:26:02

标签: haskell

Data.Lists.Split实际上并没有使用winHugs解释器。可以通过splitEvery 3 ['a'..'z']函数获取

是否可以在没有Data.Lists.Split的情况下实现这一目标? 单独的整数列表[5,5,5,6,6,6] - >每三个数字[555,666] concat

应为 [Int] - > [Int]

6 个答案:

答案 0 :(得分:4)

是的,这很有可能。你可以这样继续:

  • 首先编写一个带三位数字的函数,然后将它们“连接”成一个数字(使用乘法和加法很容易)。
  • 然后你编写另一个函数,它接受一个列表并使用前一个函数处理三个元素。基本上,该函数的定义看起来像map的定义,除了你在非空的情况下处理三个元素而不是一个元素(即你使用像x1:x2:x3:xs这样的模式),你调用之前定义的函数而不是作为论据给出的。

答案 1 :(得分:3)

以下是适用于您的目的的splitEvery实施:

import Data.List

splitEvery _ [] = []
splitEvery n xs = chunk : splitEvery n remaining
    where (chunk, remaining) = splitAt n xs

答案 2 :(得分:3)

让我们创建一个通用函数,对给定数量的项进行分组,并将给定函数应用于每个组。

groupMap :: ([a] -> b) -> Int -> [a] -> [b]
groupMap f n xs = go xs
    where go [] = []
          go xs = f (take n xs) : go (drop n xs)

好的,现在我们应该传递什么f

intListToInt :: [Int] -> Int
intListToInt xs = go xs 0
    where go []     v = v
          go (x:xs) v = go xs (x + v*10)

你可以通过各种不同的方式来写这个;我正在尝试使用主力辅助技术。请注意,此类型签名与groupMap的第一个参数很好地对齐。无论如何......让我们看看它是否有效!

ghci> groupMap intListToInt 3 [5,5,5,6,6,6]
[555,666]

耶!它甚至适用于其他东西。 (一些粗略的用法跟随......)

ghci> groupMap (read :: String -> Int) 5 "1234554321"
[12345,54321]
ghci> groupMap (read :: String -> Bool) 4 "TrueTrueTrue"
[True,True,True]
ghci> groupMap sum 2 [1,2,3,4,5,6]
[3,7,11]

注意:如果我没弄错的话,intListToInt可以从更严格的方面受益:

{-# LANGUAGE BangPatterns #-}

intListToInt xs = go xs 0
    where go []     !v = v
          go (x:xs) !v = go xs (x + v*10)

虽然我并不熟悉Hugs支持哪种语言。

答案 3 :(得分:2)

使用showconcatread

map (read . (>>= show)) . splitEvery 3

答案 4 :(得分:1)

可能的解决方案:

这是一种可能的解决方案,仅使用Prelude中的函数:

group3 :: [Int] -> [Int]
group3 [] = []
group3 xs = toSingleNum (take 3 xs): (group3 (drop 3 xs))
     where toSingleNum ys = read $ concat $ map show ys

当然,有无数种方法可以做到这一点。这是一个。


说明:

group3使用takedrop函数以及自然递归来将列表拆分为3个组,并将toSingleNum应用于每个组。

忽略takedrop的应用,该功能大致如下:

group3 [1,2,3,4,5,6,7,8,9]
toSingleNum [1,2,3] : group3 [4,5,6,7,8,9]
toSingleNum [1,2,3] : toSingleNum [4,5,6] : group3 [7,8,9]
toSingleNum [1,2,3] : toSingleNum [4,5,6] : toSingleNum [7,8,9] : group3 []
toSingleNum [1,2,3] : toSingleNum [4,5,6] : toSingleNum [7,8,9] : []

应用toSingleNum后,我们会:

123 : 456 : 789 : []
[123, 456, 789]

toSingleNum将数字列表转换为单个数字。

toSingleNum [1, 3, 4]
>>> 134
toSingleNum [12, 13, 14]
>>> 121314

toSingleNum中的转化是通过将数字转换为String,然后将它们组合,然后转换回数字来完成的。

toSingleNum [1, 3, 4]
read $ concat $ map show [1, 3, 4]
read $ concat $ ["1", "3", "4"]
read $ "134"
134

进一步阅读:

如果您对Haskell感兴趣,我会推荐Graham Hutton出色的“Haskell编程”,或者Haskell Wiki上列出的教程之一。

答案 5 :(得分:0)

首先,将列表拆分为块:

chunk n = unfoldr split
  where
    split [] = Nothing  -- stop
    split xs = Just $ splitAt n xs  -- keep going
ghci> chunk 3 [1..6]
[[1,2,3],[4,5,6]]

chunk函数继续从输入列表中删除n个大小的块,直到列表为空。 (顺便说一句,unfoldr是标准库中最不受重视的函数之一。)

然后将每个块转换为数字:

cumulate = foldl' (\x y -> x * 10 + y) 0
ghci> cumulate [4,5,6]
456

现在,将这两个功能组合在一起:

coalesce = map cumulate . chunk
ghci> coalesce [5,5,5,6,6,6]
[555,666]