2013-03-21 167 views
15

我必须在Haskell元组中获得第n个元素。元组是这样的: (3,5,“String1”,“String2”,“String3”,“String4”,“String5”,“String6”,“String7”,“String8”,“String9”,“ String10" )。你能给我一个想法,以便我能解决这个问题吗? 谢谢。如何从Haskell的10元组中获得第n个元素?

回答

22

正如你可能会或可能不知道FST和snd仅2元元组工作即

fst' (a,b) = a 

你必须写你自己的,据我所知

get5th (_,_,_,_,a,_,_,_,_,_) = a 

,你可以看到你可能想要定义你自己的类型。

36

你可以用模式匹配来做到这一点。就像你可以匹配两个或三个值的元组一样,你可以匹配一个十值元组。

let (_, _, _, _, _, _, _, _, _, x, _, _) = tuple in x 

但是,机会是你不希望做到这一点。如果你试图从一个元组中获得第n个值,那么你几乎肯定会使用错误的类型。在Haskell中,不同长度的元组是不同的类型 - 它们从根本上不兼容。就像IntString是不同的,(Int, Int)(Int, Int, Int)也完全不同。

如果你想要一个数据类型,你可以得到第n个元素,你需要一个列表:像[String]。随着名单,你可以使用!!运营商索引(它从0开始),所以你可以只是做:

myList !! 9 

拿到10元。

鉴于你的例子,我怀疑你想要的类型如(Int, Int, [String])而不是一个巨大的元组。这将让你有两个数字和任意数量的字符串;您可以使用上述!!运算符按索引获取字符串。

+0

非常感谢你的回答。我有一个输入为10元组,我必须从中获取元素。我想知道是否容易将元组分成2个不同的列表:首先是2个整数列表和8个字符串列表? – jason 2013-03-21 21:30:11

+1

@ user1954132:要做到这一点,无论如何你都必须对元组进行模式匹配。如果你不能把输入作为一种不同的类型,你必须在某个时候对它进行模式匹配,这会有点尴尬。你可以通过用名称替换我的例子中的'_'来获取值 - 模式中的'_'只意味着你不关心那个位置的值。 – 2013-03-21 21:32:39

+2

建议使用'!!'不是一个好主意,因为它是部分的,而且更糟糕的是建议使用列表通过索引访问项目。 [Vector's'!?'](http://hackage.haskell.org/packages/archive/vector/0.10.0.1/doc/html/Data-Vector.html#v:-33--63-)手很好。 – 2013-03-22 06:11:41

-2

我在查找相同问题的解决方案时看到了您的问题。我已阅读“!!”运营商是一个不好的解决方我已经想到了一个解决方案:

例如,如果你在你的列表中的每个元组三个要素,你可以这样做:

nTuple :: [(a, a, a)] -> Integer -> Integer -> [a] 
nTuple list group position = [ fst x | x <- (concat [ fst x | x <- (zip [(zip[t1, t2, t3][0..]) | (t1, t2, t3) <- list ] [0..]) , snd(x) == group ]) , snd(x) == position] 

现在,一些测试用例:

*Main> nTuple [("l","m","n"),("o","p","q"),("r","s","t")] 2 1 
["s"] 

*Main> nTuple [("l","m","n"),("o","p","q"),("r","s","t")] 0 2 
["n"] 

*Main> nTuple [("l","m","n"),("o","p","q"),("r","s","t")] 100 2 
[] 

*Main> nTuple [("l","m","n"),("o","p","q"),("r","s","t")] 2 100 
[] 

解说步骤通过上述函数的步骤:

1.Split元件,并把一个指数:

[ zip[t1,t2,t3][0..] | (t1,t2,t3) <- [("l","m","n"),("o","p","q"),("r","s","t")]] 

result: [[("l",0),("m",1),("n",2)],[("o",0),("p",1),("q",2)],[("r",0),("s",1),("t",2)]] 

2.对每个列表放一个索引。现在我们在每个组中都有组和职位。我们可以选择一组。例如“snd(x)== 1”的组编号为1(第一组为0)

[ fst x | x <- [([("l",0),("m",1),("n",2)],0),([("o",0),("p",1),("q",2)],1),([("r",0),("s",1),("t",2)],2)] , snd(x) == 1 ] 

result: [[("o",0),("p",1),("q",2)]] 

4.我们列出了一个列表。 Whe在单元列表中连接元组

concat [[("o",0),("p",1),("q",2)]] 

result: [("o",0),("p",1),("q",2)] 

5.最后,我们通过索引得到一个元素。在这个例子中,我们得到了第二个元素(第一个元素是“0”位置)

[ fst x | x <- [("o",0),("p",1),("q",2)] , snd(x) == 2] 

result ["q"] 
+1

这与问题有什么关系? – dfeuer 2016-05-24 20:51:18

+0

用户在给出该元素的位置后是否想要获取元素? 请慢慢阅读我的回复。我不明白你的反对票。 我想,我的“nTuple”函数是用户想要的。 :/ – Alex 2016-05-24 22:40:18

+1

问题与从单个大元组中提取元素有关。你的答案与元组列表有关。 – dfeuer 2016-05-25 07:20:23

2

如果您只需要为每个元组这样做一次,你需要在一次所有的元素,你可以简单地使用

let (x, y, s1, s2, s3, s4, s5, s6, s7, s8) = someTuple 
in ... 

并直接使用这些值。