[英]Haskell list comprehension 0's and 1's
我正在尝试编写一个函数
row :: Int -> Int -> [Int]
row n v
返回一个n
整数的列表,全部为0
,除了第v
个元素,需要为1
。
例如,
row 0 0 = []
row 5 1 = [1,0,0,0,0]
row 5 3 = [0,0,1,0,0]
我是Haskell的新手,对此有很多困难。 特别是我无法弄清楚如何让它重复0
。 我理解构建列表的概念,比如说[1..n]
,但我得到[1,2,3,4,5]
任何有关这方面的帮助将不胜感激。 谢谢。
尝试:
let row n v = map (\x -> if x == v then 1 else 0) [1..n]
这是一个“monadic”解决方案:
row n v = [(v-1, 0), (1, 1), (n-v, 0)] >>= (uncurry replicate)
replicate
函数多次重复给定值,例如replicate (v-1) 0
给出v-1
零的列表。 uncurry
用于修改replicate
以接受元组而不是两个单个参数。 有趣的算子>>=
是monad的核心; 对于列表,它与带有翻转参数的concatMap
相同。
有一个全面的清单:
row n v = [if x == v then 1 else 0 | x <- [1..n]]
或者使用fromEnum
(感谢dave4420)
row n v = [fromEnum (x == v) | x <- [1..n]]
这应该也有效:
row n v = replicate (v-1) 0 ++ [1] ++ replicate (n-v) 0
还有另一个解决方案,递归地构建列表:
row :: Int -> Int -> [Int]
row 0 _ = []
row n 1 = 1 : (row (n-1) 0)
row n m = 0 : (row (n-1) (m-1))
并且更具可读性,其中零被“采用”:
row :: Int -> Int -> [Int]
row 0 _ = []
row n m = take (m - 1) zeros ++ [1] ++ take (n - m) zeros
where zeros = (iterate id 0)
一个带有两个临时变量c和lst的简单递归循环。 c用于计数,lst是我们必须返回的列表。
row :: Int -> Int -> [ Int ]
row 0 0 = []
row n v = rowHelp n v 1 [] where
rowHelp n v c lst
| c > n = lst
| v == c = rowHelp n v ( c + 1 ) ( lst ++ [ 1 ] )
| otherwise = rowHelp n v ( c + 1 ) ( lst ++ [ 0 ] )
〜
〜
haskell的乐趣在于它让你编写程序非常像你表达算法的方式。 所以尝试:
row n v = [if (x `mod` v==0) then 1 else 0 | x <- [1..n] ]
首先,您创建一个从1,2到n的列表。 然后检查数字是否可以被v整除,如果是,则在输出列表中插入1,如果不是0。
例子:
> row 0 0
[]
> row 5 1
[1,0,0,0,0]
> row 5 3
[0,0,1,0,0]
> row 15 3
[0,0,1,0,0,1,0,0,1,0,0,1,0,0,1]
HTH Chris
我想基于Chris的解决方案展示自上而下的方法:
row n v = result
where
result = take n numbers -- our result will have a length of n
numbers = map trans [1,2,..] -- and is some transformation of
-- the list of natural numbers
trans e
| e `mod` v == 0 = 1 -- let every v-th element be 1
| otherwise = 0 -- 0 otherwise
这种风格强调了函数式编程的想法,一个写下什么样的一定值row nv
应该是 ,而不是试图写下的功能是什么。 回忆一个关于鲜为人知的语法萨特的一个众所周知的笑话,人们可以说,在纯粹的函数编程函数中什么都不做 ,它们就是这样 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.