2014-09-28 107 views
1

我有一个结构Haskell - 如何获取列表中的列表元素?

type MyDatabase = [ (String, [String]) ] 

鉴于第一个字符串,我想经历数据库,并找到匹配的项,然后返回伴随它的列表。

lookup :: MyDatabase -> String -> [String] 
lookup dataBase str = [ list | (label, [list]) <- dataBase, str == label ] 

这是每次返回一个空列表。

+0

函数['lookup'(HTTP://hackage.haskell。 org/package/base-4.7.0.1/docs/Prelude.html)已经存在。 – 2014-09-29 17:23:21

回答

4

您几乎拥有列表理解权,如果您拥有数据库[("foo", ["bar"])]并且您尝试lookup [("foo", ["bar"])] "foo",这将返回一些内容。如果你的数据库是[("foo", ["bar", "baz"])],它将不起作用。这是因为数据库中的元素与模式相匹配,只有一个元素作为其关联的字符串列表,所以如果某个键没有关联的元素或关键元素很多,它就不起作用。您可以通过将其更改为(label, list) <- dataBase来轻松修复此问题。

此外,你也可以使用其内置于Prelude具有类型

lookup :: Eq a => a -> [(a, b)] -> Maybe b 

然后,你可以专门它为你的类型

dbLookup :: MyDatabase -> String -> Maybe [String] 
dbLookup dataBase str = lookup str dataBase 
-- Or just 
-- dbLookup = flip lookup 
-- Or just 
-- dbLookup :: String -> MyDatabase -> Maybe [String] 
-- dbLookup = lookup 
+0

谢谢你的帮助! – Aserian 2014-10-06 03:38:49

3

一个小调整是lookup功能需要你有什么:

lookup :: MyDatabase -> String -> [String] 
-- lookup ...  = [ list | (label, [list]) <- dataBase, str == label ] 
lookup dataBase str = [ s | (label, list) <- dataBase, str == label 
          , s <- list ] 

如果数据库中的条目在同一标签下有重复的条目,则将按照您的类型签名将所有值集中在一个字符串列表中。

如果你只想要第一个匹配的条目,你把刚才的第一个匹配的条目,并与concat打开它:

lookup dataBase str = concat . take 1 $ 
         [ list | (label, list) <- dataBase, str == label] 
+0

你确定要在那里重用'str'这个名字吗?这在技术上是正确的,但看起来很混乱。 – 2014-09-29 02:15:15

+0

@ØrjanJohansen谢谢,将解决它。 ......固定。 – 2014-09-29 04:00:15

+0

感谢您的帮助!完美工作。 – Aserian 2014-10-06 03:39:29