Haskell:从输入列表创建一个列表元组

bil*_*bob 2 haskell split tuples list

我正在尝试设置一些功能来帮助我正在处理的当前项目。我是 Haskell 的新手,正在努力实现我想要的功能。

我有一个列表,[a]并希望它输出四个不同列表的元组,其中列表([b],[b],[b],[b])中的每个项目[a]依次放入输出元组中的下一个列表。所以输入列表中的第一个元素[a]进入第一个列表[b],第二个元素[a]进入第二个列表[b],第三个元素[a]进入第三个列表[b],依此类推。我曾尝试使用 chunksOf 和 splitEvery/splitAt 但无法获得正确的输出。和帮助将不胜感激!谢谢!

Wil*_*sem 7

您每次“旋转”四元组并添加到第一个元素。所以我们可以用一个foldr看起来像这样的模式来实现:

toFour :: [a] -> ([a], [a], [a], [a])
toFour = foldr (\a (bs, cs, ds, as) -> (a:as, bs, cs, ds)) ([], [], [], [])
Run Code Online (Sandbox Code Playgroud)

或以无可辩驳的模式:

toFour :: [a] -> ([a], [a], [a], [a])
toFour = foldr (\a ~(bs, cs, ds, as) -> (a:as, bs, cs, ds)) ([], [], [], [])
Run Code Online (Sandbox Code Playgroud)

所以这(bs, cs, ds, as)是我们为列表尾部生成的 4 元组,我们向右“旋转”以构造元组(as, bs, cs, ds),然后将项目添加a到 4 元组的第一个列表中。

对于整数列表,这给了我们:

Prelude> toFour [1..2]
([1],[2],[],[])
Prelude> toFour [1..3]
([1],[2],[3],[])
Prelude> toFour [1..4]
([1],[2],[3],[4])
Prelude> toFour [1..5]
([1,5],[2],[3],[4])
Prelude> toFour [1..6]
([1,5],[2,6],[3],[4])
Prelude> toFour [1..10]
([1,5,9],[2,6,10],[3,7],[4,8])
Run Code Online (Sandbox Code Playgroud)

当我们使用不可辩驳的模式时,这是惰性完成的,因此我们可以例如分配无限列表的元素,然后以获取第二项的前 10 个元素为例:

Prelude> (\(_, l, _, _) -> take 10 l) (toFour [1..])
[2,6,10,14,18,22,26,30,34,38]
Run Code Online (Sandbox Code Playgroud)

  • 这是一个聪明的解决方案!我认为通过使用列表或序列而不是元组,它也可以推广到任意数量的列表。 (2认同)