【问题标题】:Haskell list comprehension 0's and 1'sHaskell 列表理解 0 和 1
【发布时间】:2011-10-05 07:58:20
【问题描述】:

我正在尝试编写一个函数

row :: Int -> Int -> [Int]
row n v

返回n 整数列表,所有0,除了vth 元素,它必须是1

例如,

row 0 0 = []
row 5 1 = [1,0,0,0,0]
row 5 3 = [0,0,1,0,0]

我是 Haskell 的新手,在这方面遇到了很多困难。特别是我不知道如何让它重复0's。我理解构建列表的概念,比如说[1..n],但我只是得到[1,2,3,4,5]

对此的任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 你好涮涮锅。如果您认为您的问题已得到解答,请选择其中一个答案作为已接受的答案。这样,其他人可以快速找到适合您问题的解决方案,而无需查看所有答案。您可以通过单击问题左侧的复选标记来选择答案。

标签: list haskell


【解决方案1】:

试试:

let row n v = map (\x -> if x == v then 1 else 0) [1..n]

【讨论】:

  • 更短:row n v = map (fromEnum.(== v)) [1..n]
  • @Landei:更短,但有点混淆了含义。
【解决方案2】:

这里是“一元”解决方案:

row n v = [(v-1, 0), (1, 1), (n-v, 0)] >>= (uncurry replicate)

replicate 函数将给定值重复多次,例如replicate (v-1) 0 给出了 v-1 零的列表。 uncurry 用于修改 replicate 以接受一个元组而不是两个单个参数。有趣的运算符>>= 是monad 的核心;对于列表,它与带有翻转参数的concatMap 相同。

【讨论】:

  • 这可能是最好的解决方案,因为它非常容易概括。
  • 可能确实是最聪明的,但不一定是最容易阅读的
  • 我刚开始使用类似 Ankur 的解决方案,但 replicate 的重复困扰了我。
  • 这个“解决方案”为第 0 0 行给出 [1],它应该评估为 []。
【解决方案3】:

有一个完整的列表:

 row n v = [if x == v then 1 else 0 | x <- [1..n]]

或使用fromEnum(感谢 dave4420)

 row n v = [fromEnum (x == v) | x <- [1..n]]

【讨论】:

  • 最短路径是fromEnum
【解决方案4】:

这也应该有效:

row n v = replicate (v-1)­ 0 ++ [1] ++ repl­icate (n-v)­ 0

【讨论】:

    【解决方案5】:

    还有另一种解决方案,递归地建立列表:

    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)
    

    【讨论】:

      【解决方案6】:

      带有两个临时变量 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 ] )
      

      ~
      ~

      【讨论】:

        【解决方案7】:

        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 克里斯

        【讨论】:

        • 似乎 mod 部分是您的发明,我在问题中看不到任何 eachevery。至少你的第二个例子是不正确的。
        【解决方案8】:

        我喜欢根据 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 n v这样的特定值应该是,而不是试图写下函数的作用时间>。回想一下关于鲜为人知的编程语言萨特的一个众所周知的笑话,人们可以说在纯函数式编程中,函数什么都不做,它们只是

        【讨论】:

        • 创建一个无限列表,并以它的开头对我来说似乎有点程序化。你写了 2 个语句,它们都做一些事情(计算无限列表然后开始)。这根本不是(IMO)写事情应该如何,而是更多如何去做,这是你说的不应该做的。 map trans [1..n] 似乎很容易阅读,不是吗?
        • 很抱歉你不喜欢它,我没有说它是最有效或最短的源代码方式。
        猜你喜欢
        • 1970-01-01
        • 2021-01-12
        • 2022-01-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多