嘿,我是函数式编程和学习haskell的新手 我想知道我是否能够在列表中拆分元素并将它们分成两部分。
我已经看到了splitAt
操作,它只在指定的索引值/位置
splitAt 3 [1,2,3,4,5] -> [1,2,3][4,5]
现在我想知道我有一个随机字符[A,S,D,F,G,H,J,K,U,Y,R,E,W,V,B,N]
的列表,
我想将其拆分为[A,S][D,F][G,H][J,K].... and so on
..
我完全被困在这! 请帮帮我!
答案 0 :(得分:5)
你可以自己编写一个函数:
mySplit :: Int -> [a] -> [[a]]
mySplit n [] = []
mySplit n xs = (take n xs):(mySplit n (drop n xs))
演示:
λ> mySplit 2 [1,2,3,4,5,6]
[[1,2],[3,4],[5,6]]
λ> mySplit 2 [1,2,3,4,5,6,7]
[[1,2],[3,4],[5,6],[7]]
另一种方法是使用split包:
λ splitEvery 3 ['a'..'z']
["abc","def","ghi","jkl","mno","pqr","stu","vwx","yz"]
答案 1 :(得分:2)
您还可以继续使用splitAt
,只需手动递归即可:
chunks :: Int -> [a] -> [[a]]
chunks n [] = []
chunks n xs = head : (chunks n tail)
where (head, tail) = splitAt n xs
λ> chunks 2 [1,2,3,4,5])
[[1,2],[3,4],[5]]
我认为这可能更有效(无需明确评估take
和drop
),但根据documentation for Data.List:
当n不是
(take n xs, drop n xs)
(_|_
)时,相当于splitAt _|_ xs = _|_
。
我觉得总有不止一种方法可以做到这一点!有趣的是看每个答案如何使用不同的模式匹配方法。
答案 2 :(得分:2)
首先在提出这样的问题时,请指定您想要的类型签名!因此,您希望从平面列表中创建(给定一个常量子列表长度)整个列表列表。这表明签名
splitOfLen :: Int -> [a] -> [[a]]
在你开始实施之前,很聪明地看看以前是否有人这样做过:
如果你想自己动手,你应该从splitAt
开始(它将一个前缀分开)并继续进行,同时保留任何内容:
splitsOfLen l xs = case splitAt l xs of
(p, []) -> [p]
(p, r) -> p : splitsOfLen l r
答案 3 :(得分:0)
在名为chunksOf
的 Data.Lists.Split 中有一个很棒的功能,它具有参数2 wiLL从列表中拉出的对。 chunksOf
会将最后一个奇数元素从列表中拉出来。假设有3个元素,它将在列表中产生2个和1个元素。
以下配对功能还从列表中拉出最后一个落后者。
pairs = takeWhile (not.null) . map (take 2) . iterate (drop 2)
我认为以下情况更好。它是为对设置的,但可以参数化以执行任何大小的块。它将采用任何列表并包含单个元素。
np ls = [take 2 (drop a ls)|a<-[0,2..(length ls)-1]]