如何在Haskell中从10元组中获取第n个元素?

问题描述 投票:0回答:7

我必须获取 Haskell 元组中的第 n 个元素。元组是这样的: (3,5,“字符串1”,“字符串2”,“字符串3”,“字符串4”,“字符串5”,“字符串6”,“字符串7”,“字符串8”,“字符串9”,“字符串10”)。你能给我一个想法,以便我可以解决这个问题吗? 谢谢。

haskell tuples
7个回答
49
投票

您可能知道也可能不知道 fst 和 snd 仅适用于 2 元素元组,即

fst' (a,b) = a

据我所知,你必须自己写

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

如您所见,您可能想要定义自己的类型。


48
投票

你可以通过模式匹配来做到这一点。就像您可以匹配二值或三值元组一样,您也可以匹配十值元组。

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

但是,您很可能不想这样做。如果您尝试从元组中获取第 n 个值,那么您几乎肯定使用了错误的类型。在 Haskell 中,不同长度的元组是不同的types——它们从根本上是不兼容的。就像 Int

String
 不同一样,
(Int, Int)
(Int, Int, Int)
 也完全不同。

如果您想要一种可以获取第 n 个元素的数据类型,那么您需要一个列表:类似

[String]

 的东西。对于列表,您可以使用 
!!
 运算符进行索引(从 0 开始),因此您可以这样做:

myList !! 9

获取第10个元素。

鉴于您的示例,我怀疑您想要像

(Int, Int, [String])

 这样的类型,而不是一个巨大的元组。这将让你有两个数字和任意数量的字符串;您可以使用上面的 
!!
 运算符按索引获取字符串。


26
投票
您可能想使用

元组包中的选择函数


5
投票
如果每个元组只需执行一次此操作,并且一次需要所有元素,则可以简单地使用

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

并直接使用这些值。


1
投票
我认为你最好使用记录类型,例如:

data MyRec = MyRec {myrecfoo::Double, myrecbar::String, myrecbaz::String}
然后使用记录访问器:

baz = myrecbaz rec
但是如果您想要/需要坚持使用元组并且字段少于 20 个,您可以使用 

Control.Lens.Tuple


0
投票
我在寻找同一问题的解决方案时看到了你的问题。我读过“!!”运算符是一个糟糕的解决方案。我想到了一个解决办法:

例如,如果列表中的每个元组都有三个元素,您可以这样做:

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.拆分元素并放置索引:

[ 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.为每个列表放置一个索引。现在我们有小组以及每个小组内的职位。

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

3.我们可以选择一个组。例如组号 1(第一组是 0),“snd(x)==1”

[ 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.我们有一个清单。何时将元组连接到单个元组列表中

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"]
    

0
投票
例如,您有 4 个方向,西、东、北和南,并且您想要提取每个方向的值(假设元组的方向按 W E N S 的顺序排列)

Coord::(Int,Int,Int,Int) Coord = (0,10,0,5)
如果您尝试像这样提取值

let (W,E,N,S)= Coord
你的编译器会向你尖叫,为了解决这个问题,你必须为每个值都有吸气剂(是的)

getW (W,_,_,_) = W getE (_,E,_,_) = E getN (_,_,N,_) = N getS (_,_,_,S) = S
就这样吧!

© www.soinside.com 2019 - 2024. All rights reserved.