0

我正在研究一个非常复杂(至少对我来说很复杂)的函数,我想用它来计算列表中的单词与数据库中的单词对应的次数。

使用随机词的示例:

let input = [("InputName", ["dog", "cat", "cat"...]), ...]
let database = ["dog", "cat", "badger"...]

经过几个小时的心理体操,我想出了这个几乎可以工作的可怕功能。我已经对其进行了简化,因此它在本示例的上下文中是有意义的:

findMatches input database = [ (snd x, wordCount (snd x)) | x <- input ]
    where
        wordCount ys = sum[ if y `elem` database then 1 else 0 | y <- ys ]

我的目标,我的希望,我的愿望是输出如下:

[("dog", 1), ("cat", 2), ("badger", 0)]

任何朝着正确方向提出的建议或推动将不胜感激。

编辑

我终于做了一个有效的功能。catWordCount 计算数据库条目在输入中出现的次数。我正在使用 fold 进行更好的实现。

let input = words "5 4 10 0 1 9 1"
let database = [("C1", words "1 2 3 4 5"), ("C2", words "6 7 8 9 10")]

catwordCount input database

catWordCount fs zs = [ (fst f, inputSearch (snd f)) | f <- fs ]
    where
        inputSearch gs = [ (g, wordCount [g]) | g <- gs ]
        wordCount hs = sum[ if h == z then 1 else 0 | h <- hs, z <- zs ]

和输出:

(["C1", [("1",2),("2",0),("3",0),("4",1),("5",1)])
(["C2", [("6",0),("7",0),("8",0),("9",1),("10",1)])
4

2 回答 2

3

您可以保留Map为每个项目更新的计数。由于您不想包含输入列表中不在数据库中的项目,如果我理解正确,

alter :: Ord k => (Maybe a -> Maybe a) -> k -> Map k a -> Map k a

是一个很好的方法。k查找提供的键,如果存在,更新函数的参数将为 we Just value,否则为Nothing。如果更新函数的结果是Nothing,则该键将从 中删除Map(或不添加,如果它不存在),如果结果是Just something,则该键将与something更改的Map.

因此,您从Map将每个项目映射到 0 开始,

m0 :: Map String Int
m0 = fromList $ zip database (repeat 0)

要更新,如果项目在 中,您希望增加计数database,否则不更改任何内容,

incr :: Maybe Int -> Maybe Int
incr (Just n) = Just (n+1)
incr Nothing  = Nothing

或者,更短的,incr = fmap (+1)使用.FunctorMaybe

然后得到的地图很简单

finalMap :: Map String Int
finalMap = foldl (flip $ alter incr) m0 $ snd input

如果你想要一个列表而不是一个Map,只需调用assocsor toListon finalMap

于 2012-12-20T20:19:25.847 回答
0

它可能不是您正在寻找的,但试试这个:

import Data.List

countMatches :: [(String, [String])] -> [(String, Int)]
countMatches = map (\l -> (head l, length l)) . group . sort . concat . map snd

希望函数组合不会太混乱。我会一步一步来的。假设您使用输入运行此函数

[("", ["a", "b"]), ("", ["b", "c", "x", "a"]), ("", ["y", "b", "z"])]

map snd是之后

[["a", "b"], ["b", "c", "x", "a"], ["y", "b", "z"]]

之后concat

["a", "b", "b", "c", "x", "a", "y", "b", "z"]

之后sort

["a", "a", "b", "b", "b", "c", "x", "y", "z"]

之后group

[["a", "a"], ["b", "b", "b"], ["c"], ["x"], ["y"], ["z"]]

最后map (\l -> (head l, length l))产生

[("a", 2), ("b", 3), ("c", 1), ("x", 1), ("y", 1), ("z", 1)]
于 2012-12-20T20:24:35.853 回答