Haskell : 在元组列表上使用 `find` 函数
Haskell : using the `find` function on a list of tuples
我想知道是否有人可以帮助我。假设我有一个 (String,Int)
类型的元组和一个 [("Strength",12),("Stamina",60),("Health",100)]
类型的元组列表。
如果我实际上不知道元组在列表中的顺序但只是否存在包含字符串 "Stamina"
的某个元组?
我试过了
value = snd ( find ("Stamina", _ ) stats )
其中 stats
是元组列表,value
定义为
value :: a -> Int
..但它不起作用:/那么有什么想法吗?我特别打算使用 find
.
您似乎在尝试使用模式作为 find
的参数。不幸的是,那行不通。您只能在少数地方进行模式匹配,例如守卫和 case
表达式。
正如 Jubobs 在他的评论中所说,在这种情况下使用 Data.List.lookup
是理想的,但使用 Data.List.find
也是绝对可行的。
如果你看一下 Data.List.find
的类型,你会发现它看起来像这样:
find :: Foldable t => (a -> Bool) -> t a -> Maybe a
这告诉你两件重要的事情:
第一个参数必须是谓词函数,即当它的参数是您要查找的值时 returns True 和 returns False 的函数否则
函数return是一个Maybe a
,这意味着它可能returnNothing
而你必须处理这个
创建谓词函数非常简单。您只需要使用 ==
运算符测试元组的第一个值的东西,也许是像这样的 lambda 函数:
\(x, _) -> x == "Stamina"
现在您可以这样调用 find
:
find (\(x, _) -> x == "Stamina") stats
或者,您可以创建一个通用函数来将元组的第一个元素与已知值进行比较,例如:
matchFirst x (y, _) = x == y
稍后使用 matchFirst
函数作为 find
的参数:
find (matchFirst "Stamina") stats
现在让我们来看看我的第二点:你如何处理 find
没有找到任何东西?
如果您完全确定它总是会成功,您可以简单地使用 Data.Maybe.fromJust
从 Maybe
中提取元组,如下所示:
value = snd $ fromJust $ find (matchFirst "Stamina") stats
否则,如果查找确实失败,您可以做很多事情。例如,您可以使用 Data.Maybe.fromMaybe
的合理默认值,或者您可以将 value
更改为 Maybe Int
.
类型
最后,最后一件事:你说过 value
的类型是 a -> Int
,即一个接受任何东西的函数并且 return 是 Int
。实际情况并非如此。相反,它只是一个值。
更多选择,不一定比上面的好:
按照 OP 的建议使用模式
find (\c -> case c of ("A", _) -> True ; _ -> False) [("B",4), ("A", 5), ("C", 7)]
同理,利用扩展
{-# LANGUAGE LambdaCase #-}
find (\case ("A", _) -> True ; _ -> False) [("b",4), ("A", 5), ("C", 7)]
此处使用 fst
和等式 ==
的简单单行代码。
您需要导入 Data.List
和 Data.Maybe
。
> let set stats = [("Strength",12),("Stamina",60),("Health",100)]
> snd $ fromJust $ find ((=="Strength") . fst) stats
12
fn :: Eq a => a -> [(a, b)] -> b
fn x = snd . fromJust . find ((== x) . fst)
那么你会
tuples :: [(String, Int)]
tuples = undefined -- a list of tuples
string :: String
string = "Stamina"
value :: Int
value = fn string tuples
我想知道是否有人可以帮助我。假设我有一个 (String,Int)
类型的元组和一个 [("Strength",12),("Stamina",60),("Health",100)]
类型的元组列表。
如果我实际上不知道元组在列表中的顺序但只是否存在包含字符串 "Stamina"
的某个元组?
我试过了
value = snd ( find ("Stamina", _ ) stats )
其中 stats
是元组列表,value
定义为
value :: a -> Int
..但它不起作用:/那么有什么想法吗?我特别打算使用 find
.
您似乎在尝试使用模式作为 find
的参数。不幸的是,那行不通。您只能在少数地方进行模式匹配,例如守卫和 case
表达式。
正如 Jubobs 在他的评论中所说,在这种情况下使用 Data.List.lookup
是理想的,但使用 Data.List.find
也是绝对可行的。
如果你看一下 Data.List.find
的类型,你会发现它看起来像这样:
find :: Foldable t => (a -> Bool) -> t a -> Maybe a
这告诉你两件重要的事情:
第一个参数必须是谓词函数,即当它的参数是您要查找的值时 returns True 和 returns False 的函数否则
函数return是一个
Maybe a
,这意味着它可能returnNothing
而你必须处理这个
创建谓词函数非常简单。您只需要使用 ==
运算符测试元组的第一个值的东西,也许是像这样的 lambda 函数:
\(x, _) -> x == "Stamina"
现在您可以这样调用 find
:
find (\(x, _) -> x == "Stamina") stats
或者,您可以创建一个通用函数来将元组的第一个元素与已知值进行比较,例如:
matchFirst x (y, _) = x == y
稍后使用 matchFirst
函数作为 find
的参数:
find (matchFirst "Stamina") stats
现在让我们来看看我的第二点:你如何处理 find
没有找到任何东西?
如果您完全确定它总是会成功,您可以简单地使用 Data.Maybe.fromJust
从 Maybe
中提取元组,如下所示:
value = snd $ fromJust $ find (matchFirst "Stamina") stats
否则,如果查找确实失败,您可以做很多事情。例如,您可以使用 Data.Maybe.fromMaybe
的合理默认值,或者您可以将 value
更改为 Maybe Int
.
最后,最后一件事:你说过 value
的类型是 a -> Int
,即一个接受任何东西的函数并且 return 是 Int
。实际情况并非如此。相反,它只是一个值。
更多选择,不一定比上面的好:
按照 OP 的建议使用模式
find (\c -> case c of ("A", _) -> True ; _ -> False) [("B",4), ("A", 5), ("C", 7)]
同理,利用扩展
{-# LANGUAGE LambdaCase #-}
find (\case ("A", _) -> True ; _ -> False) [("b",4), ("A", 5), ("C", 7)]
此处使用 fst
和等式 ==
的简单单行代码。
您需要导入 Data.List
和 Data.Maybe
。
> let set stats = [("Strength",12),("Stamina",60),("Health",100)]
> snd $ fromJust $ find ((=="Strength") . fst) stats
12
fn :: Eq a => a -> [(a, b)] -> b
fn x = snd . fromJust . find ((== x) . fst)
那么你会
tuples :: [(String, Int)]
tuples = undefined -- a list of tuples
string :: String
string = "Stamina"
value :: Int
value = fn string tuples