[英]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.