Haskell-两个列表的元组列表 [英] Haskell- Two lists into a list of tuples

查看:123
本文介绍了Haskell-两个列表的元组列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图实现一个函数(如下所述),它带有两个列表(每个或两者都可以是无限的)并返回列表之间所有可能的元素对的元组列表

  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]] 从上面的无限数组中提取条带列表(首先假定所有列表都是无限的,即不要担心 [] 的情况;一旦你有这个工作,纠正它在可能有限的列表上工作。)



使用条纹,实现对角线:: [[a]] - > [b]
$ b

最后,通过应用<$ c $来实现你的函数。一个特定的二维表 [[(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, and xss is the rest of the table.

这篇关于Haskell-两个列表的元组列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆