【问题标题】:How to get nth element from a 10-tuple in Haskell?如何从 Haskell 中的 10 元组中获取第 n 个元素?
【发布时间】:2013-03-11 14:20:26
【问题描述】:

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

【问题讨论】:

    标签: haskell tuples


    【解决方案1】:

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

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

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

    如果您想要一个可以获取第 n 个元素的数据类型,您需要一个列表:类似于[String]。对于列表,您可以使用 !! 运算符进行索引(从 0 开始),因此您可以这样做:

    myList !! 9
    

    获取第 10 个元素。

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

    【讨论】:

    • 非常感谢您提供这么好的答案。我有一个 10 元组的输入,我必须从中获取元素。我想了解将元组划分为 2 个不同的列表是否容易:首先是 2 个整数的列表和 8 个字符串的列表?
    • @user1954132:为此,无论如何您都必须对元组进行模式匹配。如果您无法获得不同类型的输入,则必须在某个时候对其进行模式匹配,这会有点尴尬。您可以通过将我的示例中的_ 替换为名称中的_ 来获取值,这意味着您不关心该位置的值。
    • 建议使用!! 不是一个好主意,因为它是部分的,而且建议使用列表来按索引访问项目更糟糕。另一方面,Vector's !? 很好。
    • 是的,如果你想要一个存储索引数据的结构,List 不是正确的结构。它不用于索引,更类似于控制流结构。向量或数组就是为此而设计的——就像在其他所有语言中一样。
    • @Student 这本身就是一个很深的问题,值得单独提问。 (它可能已经在 SO 的某个地方解决了。)令人不满意的是,评论长度的答案是它完全取决于你想要做什么。
    【解决方案2】:

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

    fst' (a,b) = a
    

    据我所知,你必须自己写

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

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

    【讨论】:

      【解决方案3】:

      【讨论】:

        【解决方案4】:

        我在寻找相同问题的解决方案时看到了您的问题。我读过“!!”运营商是一个糟糕的解决方案。我想到了一个解决方案:

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

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

        【讨论】:

        • 这和问题有什么关系?
        • 用户在给出该元素的位置后是否想要获取该元素?请慢慢阅读我的回复。我不明白你的反对票。我认为,我的“nTuple”功能可以满足用户的需求。 ://
        • 这个问题与从单个大元组中提取元素有关。您的答案与元组列表有关。
        • 我试图为一个或多个元组提供一个通用的解决方案。我是 Stackoverflaw 的新手。下一次我会努力进入正题。对不起。
        • 采用迂回或超通用的方法是完全可以的。但是你总是需要回头看看它是如何回答问题的,它解决了装腔作势的问题。在这种情况下,我认为不会。此外,虽然从一般到具体的工作很好,但从小到大的工作很重要。我认为对于元组列表的任何好的解决方案都将从一个单独的元组构建。事实上,如果您确切知道有多少个元组,元组列表的解决方案可能不是您想要的!
        【解决方案5】:

        如果您只需要每个元组执行一次,并且一次需要所有元素,则可以简单地使用

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

        并直接使用这些值。

        【讨论】:

          【解决方案6】:

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

          data MyRec = MyRec {myrecfoo::Double, myrecbar::String, myrecbaz::String}
          

          然后使用记录访问器:

          baz = myrecbaz rec
          

          但如果您想要/需要坚持使用元组并且字段少于 20 个,您可以使用 Control.Lens.Tuple

          【讨论】:

            猜你喜欢
            • 2021-12-22
            • 1970-01-01
            • 1970-01-01
            • 2011-03-19
            • 1970-01-01
            • 2023-03-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多