Haskell - 以不同方式映射奇数放置值和偶数放置值

时间:2010-05-31 07:45:28

标签: haskell mapping

有一种简单的方法。要取一个数字列表,比如说123456.然后将奇数放三乘,偶数乘以1.

即。 (1 * 3)+(2 * 1)+(3 * 3)+(4 * 1)+(5 * 3)+(6 * 1)

我在想某个地方的地图功能。但我不知道如何将* 3映射到奇数放置的值。哦,如果你可以给我一个不是前奏的版本,就像实际的函数或函数一样好,就好像它是从外部haskell文件中导入的那样

感谢您的帮助

5 个答案:

答案 0 :(得分:14)

好的,正如我之前在评论中写的那样,zipWith (*) (cycle [3,1]) xs正是您所寻找的。但首先,一个小的挑剔:列表的头部我会称之为第0个元素,这就是为什么我将1和3转换为: - )

我们来看一个简单的例子;让xs成为[9,8,7,3,2]cycle [3,1]只是一遍又一遍地重复它的论证,这将是一个以[3,1,3,1,3,1,...]开头的无限列表。 zipWith f xs ys做的是xs的head元素和ys的head元素,并将f(应该是两个参数的函数)应用于这些元素 - f的结果会转到zipWith结果的前面。如果x或y中的一个变空,我们就完成了;否则我们继续前进。

结果的第一个元素是(3 * 9),然后是(1 * 8)(3 * 7)(1 * 3)(3 * 2),我们就完成了!

您可以查看zipWith here的定义。

如果你确实不想使用预定义的函数,你可以定义一个'交替地图',取两个函数而不是一个,将第一个函数应用到参数列表的头部并在递归调用上切换函数。我会让你弄清楚那里的细节......

答案 1 :(得分:2)

这个怎么样,假设xs是您的数字列表:

map (uncurry ($)) (zip (cycle [((*) 1), ((*) 3)]) xs)

以下是其工作原理:

[((*) 1), ((*) 3)]是包含两个函数的列表。第一个乘以一个数字;第二个将数字乘以三。

cycle [...]创建这两个函数的无限列表,一个接一个地重复,[×1,×3,×1,×3 ......]

zip (cycle [...]) xs获取您的数字并将其与功能配对。所以如果xs是[1..6]那么你得到[(×1,1),(×3,2),(×1,3),(×3,4),(×1, 5),(×3,6)]。

$ :: (a -> b) -> a -> b函数是组合子;它需要一个函数a→b并将其应用于一个值。因此map (uncurry ($)) (zip ...)获取(函数,数字)对的列表并将该函数应用于该数字。您需要uncurry,因为列表包含对,因此要映射的函数的签名必须为((a -> b), a) -> b

这会留下结果列表;在这种情况下[1,6,3,12,5,18]。

答案 2 :(得分:1)

我的第一个想法是使用累积贴图,使用累积参数来标记它是在'偶数'还是'奇数'循环。我看到没有其他人这样做过,所以让我们看看它是怎么回事......

import Data.List (mapAccumL)

yourFunc = snd . mapAccumL mult True -- 'True' represents an odd index, starting from 1
  where
    mult True  x = (False, 3 * x)
    mult False x = (True , x)

答案 3 :(得分:0)

您仍然可以使用地图,只需先使用zip:

let list' = zip [1..] list
in map (\(cnt,val) -> if odd cnt then val * 3 else val) list'

上面你可以看到如何使结果依赖于索引以及该索引处的值。这是一个相当普遍的解决方案,通过替换lambda(map的第一个参数),您可以创建许多变体。使用cyclezipWith的更专业的解决方案更短,并且对于Haskell中的人来说非常易读。

在声明作业之后编辑并充实。

答案 4 :(得分:0)

如果你想做这种无点风格,没有比使用cycle和某种形式的zip更好的方法了。 (无点意味着,“没有命名let-bound或lambda-bound变量。”)我有两个问题:

  • 您需要多少种不同的方法来概括这个计算?
  • 您的读者对cycle和其他鲜为人知的列表函数(必须有一百个列表函数)有多熟悉?

问题越普遍,读者越熟悉,我就越有可能推荐无点风格。对于针对不太熟悉Haskell的读者的一次性解决方案,我可能会尝试递归函数:

mult31 [] = 0
mult31 [x:x':xs] = x * 3 + x' * 1 + mult31 xs
mult31 [x] = x * 3

或者如果你想变得聪明,你可以使用一对交替功能:

mult31 = m3
  where m3 (x:xs) = x * 3 + m1 xs
        m3 []     = 0
        m1 (x:xs) = x * 1 + m3 xs
        m1 []     = 0

对于Haskell老手来说,这些函数中的任何一个对于cycle使用zip函数的东西来说都不太自然,但对于刚开始的人来说,它们可能更容易理解。