【问题标题】:Apply a function to a list of items将函数应用于项目列表
【发布时间】:2014-04-22 12:52:32
【问题描述】:

我定义了一个函数f,它返回一个项目xprice,该项目存储在一个类型为[(String,String,Int)]的价格列表中

a = String
x = String
price = Int
pricesList = [(a,x,price)]

f a x ((a1, x1, price):ys) | a == a1 && x == x1 = price
                           | otherwise = f a x ys

我必须将此功能应用于项目列表,但我被卡住了。这可以使用地图吗?我想不通。

(唯一可以使用递归的函数是f)

编辑。一些例子来澄清一下

pricesList = [("apple","ipod",100),("apple","iphone",200),("samsung","galaxy",200)]
moneySpent = [("harry",1985,"apple",["iphone","ipod"]),("george",1983,"samsung",["galaxy"])]

*Main> f "apple" "iphone" pricesList
200

我需要知道一个人通过定义一个新函数花了多少钱,比如说spentBy(并在其中使用f

*Main> spentBy "harry"
300

到目前为止我做了什么:

itsThePerson name (n,_,_,_) = name == n

infoFrom name = (head . filter (itsThePerson name)) moneySpent

brand (_,_,b,_) = b
product (_,_,_,p) = p

brandPerson = brand . infoFrom
productPerson = product . infoFrom

是否可以使用mapf 函数来知道一个人购买的产品的价格总和?

(函数f 将是函数itemPrice

spentBy name = sum (map (itemPrice (brandPerson name) xxx pricesList) (productPerson name)

我的想法是否正确?

【问题讨论】:

  • 完全不清楚您要做什么。如果您有作业,请尝试逐字引用。如果您正在尝试执行一些现实世界的任务,请描述该任务。
  • 如果我理解您要执行的操作,f 是一个查找商品价格的函数,list 是您要查找的商品列表价格。对吗?
  • @mhwombat 是的,这是正确的。我需要将函数 f 应用于项目列表,而不仅仅是一项。使用地图可以吗?
  • 以后,与其改写您的问题,不如在底部添加任何说明。
  • map 接受一个列表和一个转换函数,并返回一个按元素转换的列表。你有什么样的清单?你想得到什么样的清单?

标签: haskell functional-programming


【解决方案1】:

假设你有一个三参数函数:

f :: a -> b -> c -> d

c 值列表 - list :: [b]。假设我们想将f 应用于列表中的每个项目,并使用固定的第一个和第二个参数。所以我们可以这样做:

map (f x y) list

x::ay::b 的位置。

与您的情况的唯一区别是参数的顺序。对于此类问题,请使用flip

flip :: (a -> b -> c) -> (b -> a -> c)

--original function
f :: a -> b -> c -> d

--partial application
f x :: b -> c -> d

-- flip
flip (f x) :: c -> b -> d

--partial application again
(flip (f x) y) :: b -> d

map (flip (f x) y) list :: [d]

在你的情况下,它可能会导致类似map (flip (f a) prices) list

【讨论】:

    【解决方案2】:

    如果您为f 提供了类型签名,那么您想要做什么会更清楚。我将假设f 的第三个参数是(item #, description, price) 的列表。一个例子是:

    priceList = [(1,"item 1", 1), (2,"item 2", 22), (3, "item 3", 333), (4, "item 4", 4444)]
    

    那么我们计划映射的列表必须如下所示:

    list = [(1,"item 1"), (3,"item 3"), (4, "item 4")]
    

    我们可以像这样映射list

    map (\(itemId, desc) -> f itemId desc priceList) list
    

    您可以改为编写f 来获取两个参数,将前两个参数组合成一个元组f (a,x) ((a1, x1, price):ys)。您只需要map f list

    最后,您还没有处理价格不在列表中的情况。你可以这样做:

     f _ _ _ = error "item not found"
    

    【讨论】:

      【解决方案3】:

      修改后的答案: 你试图解决的整体问题,

      • 给定一个函数 f,它采用“itemId”、“itemName”和“priceList” 并返回一个价格。
      • 您需要一个使用 f 从 [(itemId, itemName)] 列表中返回价格列表的函数

      就类型签名而言,给定:

      f :: String -> String -> [(String, String, Int)] -> Int
      

      你想要的:

      myLookup :: (String -> String -> [(String, String, Int)] -> Int) -> 
                      [(String, String, Int)] -> [(String, String)] -> [Int]
      

      其中第一个参数是查找函数f、priceList 和 itemList,输出是价格列表。

      myLookup f priceList itemList = map (\(itemId, itemName) -> 
                                                f itemId itemName priceList)
                                          itemList
      

      map 的第二个参数是一个 lambda,它从 itemList 中提取两个属性并使用 f 查找值。

      【讨论】:

      • itemID 和 itemName 对应于 [(String, String, Int)] 元组列表的第一个和第二个元素。问题是不能修改函数f。这个想法是使用map 返回一个值列表,然后生成它们中的sum
      • @warty:更正了答案。这就是你要找的吗?
      【解决方案4】:

      我可以解决我的问题:

      f a x ((a1, x1, price):ys) | a == a1 && x == x1 = price
                                 | otherwise = f a x ys
      

      使用了新功能f2

      f2 a x = f a x pricesList
      

      然后

      pricesList = [("apple","ipod",100),("apple","iphone",200),("samsung","galaxy",200)]
      moneySpent = [("harry",1985,"apple",["iphone","ipod"]),("george",1983,"samsung",["galaxy"])]
      
      
      spentBy name = sum (map (f2 (brandPerson name)) (productPerson name))
      
      itsThePerson name (n,_,_,_) = name == n
      
      infoFrom name = (head . filter (itsThePerson name)) moneySpent
      
      brand (_,_,b,_) = b
      product (_,_,_,p) = p
      
      brandPerson = brand . infoFrom
      productPerson = product . infoFrom
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-08-23
        • 2019-08-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-08
        相关资源
        最近更新 更多