简体   繁体   English

如何在具有超过 2 个元素的元组列表中搜索和编辑元组?

[英]How can I search and edit tuples in a list of tuples with more than 2 elements?

I have a list of tuples我有一个元组列表

type Sales = (String, String, Integer)

testData :: [Sales]
testData = [("Jack", "Hill", 2), ("Susan", "Smith", 5), ("Steve", "Johnson", 6)

How can I write a function that would search through the list of tuples given the first and last names and output the number, and let me edit that number?如何编写一个函数来搜索给定名字和姓氏的元组列表并输出数字,然后让我编辑该数字?

I'm trying to have something like:我试图有类似的东西:

recordSale "Jack" "Hill"   -- and the function return 2 

And another which would do:另一个可以做到的:

addSale "Jack" "Hill"     -- and it would add 1 to the database corresponding to the name

So far I've tried到目前为止我已经尝试过

recordSale tData Fname Lname= find (\(Fname, Lname, _) tData

recordSale tData Fname Lname = [(Fname, Lname, map (\tData -> tData + 1) sales) | (Fname, Lname, sales) <- tData]

nothing seems to work though, and most help I find only works with tuples with 2 elements, not 3.但似乎没有任何效果,而且我发现的大多数帮助只适用于具有 2 个元素而不是 3 个元素的元组。

It might be worthwhile to use a Data.Map .使用Data.Map可能是值得的。 If you want to stick with tuples you can break it into smaller step.如果你想坚持使用元组,你可以把它分成更小的步骤。

  1. Write a function that given a Sale returns the sale count.编写一个给定Sale返回销售计数的函数。

     saleCount :: Sale -> Integer saleCount (first, last, count) = undefined -- to do
  2. Write a function that given a name, checks if the passed tuple matches.编写一个给定名称的函数,检查传递的元组是否匹配。 (This is commonly called a predicate and will help you in the next step.) (这通常称为谓词,将在下一步中为您提供帮助。)

     isMatching :: String -> String -> Sale -> Bool isMatching first last (saleFirst, saleLast, saleCount) = undefined -- to do
  3. Use find @[] :: (a -> Bool) -> [a] -> Maybe a .使用find @[] :: (a -> Bool) -> [a] -> Maybe a While trying with find the question will arise what you want to happen, if the list does not contain or tuple or multiple tuples.在尝试查找时,如果列表不包含元组或多个元组,则会出现您想要发生的问题。

For updating the list you can have a look at Replace individual list elements in Haskell?要更新列表,您可以查看Replace individual list elements in Haskell?

As a side note, the example testData is missing the closing square bracket.作为旁注,示例 testData 缺少右方括号。

A function to search the testData is shown below.搜索 testData 的函数如下所示。

type Sales = (String, String, Integer)

testData :: [Sales]
testData = [("Jack", "Hill", 2), ("Susan", "Smith", 5), ("Steve", "Johnson", 6)]

findNumber:: [Sales] -> String -> String -> Integer
findNumber (x:xs) name1 name2  =
  findNumberIter (x:xs) name1 name2 (-1)
  where 
    findNumberIter [] _ _ number = number
    findNumberIter (x:xs) name1 name2 number =
      if xname1 == name1 && xname2 == name2 then
        findNumberIter xs name1 name2 xnumber
      else 
        findNumberIter xs name1 name2 number
      where
        (xname1,xname2,xnumber) = x

main = putStrLn $ show $findNumber testData "Jack" "Hill"

We run a tail recursion, going through the elements (x:xs) one by one.我们运行尾递归,逐个遍历元素(x:xs) For each element, we test against name1 and name2 supplied, and if found replace the output number with the matching number.对于每个元素,我们针对提供的name1name2进行测试,如果找到,则将输出编号替换为匹配的编号。

Notes:笔记:

  • This will return the last match.这将返回最后一场比赛。 You may want the first match, or perhaps you want all matches您可能想要第一场比赛,或者您可能想要所有比赛
  • This assumes a no match value of -1.这假定不匹配值为 -1。 You may wish to change the function to return a Maybe value instead您可能希望更改函数以返回Maybe
  • The search uses a local definition of the recursion, findNumberIter , and hides it so that the user interface is cleaner搜索使用递归的本地定义findNumberIter并将其隐藏,以便用户界面更清晰
  • Each element x in the list is split out into separate values using a pattern match使用模式匹配将列表中的每个元素x拆分为单独的值
  • There is almost certainly a cleaner and simpler way of doing this, but it is fine for a pedagogical approach几乎可以肯定有一种更清洁、更简单的方法,但它适用于教学方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM