Haskell-两个列表的元组列表 [英] Haskell- Two lists into a list of tuples
问题描述
我试图实现一个函数(如下所述),它带有两个列表(每个或两者都可以是无限的)并返回列表之间所有可能的元素对的元组列表
zipInf :: [a] - > [b] - > [(a,b)]
(例如,输出应该是这样的,但没有就像这样)
zipInf [0 .. 2] ['A'..'C']〜> [(0, 'A'),(1, 'A'),(0, 'B'),(1, 'B'),(0, 'C'),(2, 'A'),( 2,'B'),(1,'C'),(2,'C')]
zipInf [] [0 ..]〜> []
zipInf [0 ..] []〜> []
取9(zipInf ['A'] [0 ..])〜> [( 'A',0),( 'A',1),( 'A',2),( 'A',3),( 'A',4),( 'A',5),( 'A',6),('A',7),('A',8)]
我开始像这样实现它:
zipInf :: [a] - > [b] - > [(a,b)]
zipInf [] _ = []
zipInf _ [] = []
zipInf
我想将列表提供给一个帮助函数来生成列表,但我做的列表无法编译,也不知道如何处理无限列表。 b
$ b
助手功能 -
oneList :: [a] - > [b] [(a,b)]
oneList [] _ = []
oneList x:xs y:ys = [(x,y)] ++ oneList
这是一个很棒的练习!
如果我们将输入对放在无限表中:
<$ c (1,A)(2,A)(3,A)...
(0,B)(1,B)(2,B)(3,B) ...
(0,C)(1,C)(2,C)(3,C)...
(0,D)(1,D)(2,D)( 3,D)...
...
诀窍是遍历表在向上的斜条纹。用你的眼睛跟踪你的桌子。这张表的条纹是:
$ p $ code>(0,A)
(0,B)(1,A)
(0,C)(1,B)(2,A)
(0,D)(1,C)(2,B)(3,A)
...
所有条纹都是有限的,但表格的每个元素都在其中一个,所以如果你将它们连接在一起,每个元素将出现在连接结果的有限位置。
以下是我建议的游戏计划:
执行 stripes :: [[a]] - > [[a]]
从上面的无限数组中提取条带列表(首先假定所有列表都是无限的,即不要担心 []
的情况;一旦你有这个工作,纠正它在可能有限的列表上工作。)
使用 最后,通过应用<$ c $来实现你的函数。一个特定的二维表条纹
,实现对角线:: [[a]] - > [b]
,这是我用使用嵌套列表理解,以及其他各种方式构建)。
$ b [[(a,b)]]
的c> diagonal
注意: 名称zip是误导性的。这更像是一个笛卡儿的产品。
f :: [[a]] - >
f((x:xs):xss)= ...
让您将 x
作为第一行的第一个元素, xs
是第一行的其余部分,并且 xss
是表格的其余部分。
I am trying to implement a function (described below) that takes two lists (each or both may be infinite) and return a list of tuples of all the possible pairs of elements between the lists
zipInf :: [a] -> [b] -> [(a,b)]
(e.g the output should be like this, but doesn't have to be exactly like this)
zipInf [0 .. 2] ['A' .. 'C'] ~> [(0,'A'),(1,'A'),(0,'B'),(1,'B'),(0,'C'),(2,'A'),(2,'B'),(1,'C'),(2,'C')]
zipInf [] [0 ..] ~> []
zipInf [0 ..] [] ~> []
take 9 (zipInf ['A'] [0 .. ]) ~> [('A',0),('A',1),('A',2),('A',3),('A',4),('A',5),('A',6),('A',7),('A',8)]
I've started implementing it like this:
zipInf :: [a] -> [b] -> [(a,b)]
zipInf [] _ = []
zipInf _ [] = []
zipInf
I wanted to feed the list into a helper function to produce the lists but the one I made fails to compile and don't know how to handle infinite lists
Helper function-
oneList :: [a] -> [b] [(a,b)]
oneList [] _ = []
oneList x:xs y:ys = [(x,y)] ++ oneList
This is a great exercise!
If we lay out the pairs of your input in an infinite table:
(0,A) (1,A) (2,A) (3,A) ...
(0,B) (1,B) (2,B) (3,B) ...
(0,C) (1,C) (2,C) (3,C) ...
(0,D) (1,D) (2,D) (3,D) ...
...
The trick is to traverse the table in upward diagonal stripes. Trace the table with your eyes. The stripes of this table are:
(0,A)
(0,B) (1,A)
(0,C) (1,B) (2,A)
(0,D) (1,C) (2,B) (3,A)
...
All the stripes are finite, yet every element of the table is in one of them, so if you concatenate them together every element will appear at a finite position in the concatenated result.
Here's the gameplan I'd suggest:
Implement stripes :: [[a]] -> [[a]]
which extracts the list of stripes from an infinite array like above (start by assuming that all lists are infinite, i.e. don't worry about the []
cases; once you have that working, correct it to work on lists that might be finite).
Using stripes
, implement diagonal :: [[a]] -> [a]
which concatenates all the stripes (this is a one-liner).
Finally, implement your function by applying diagonal
of a particular 2D table [[(a,b)]]
, which is the table I started this answer with (and can be constructed using a nested list comprehension, among other various ways).
Notes:
The name zip is misleading. This is more like a cartesian product.
You know you can match patterns inside patterns, right? I.e. if
f :: [[a]] -> something
f ((x:xs):xss) = ...
Gives you
x
as the first element of the first row,xs
is the rest of the first row, andxss
is the rest of the table.
这篇关于Haskell-两个列表的元组列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!