我正在研究一个非常复杂的(至少对我很复杂)函数,我想用它来计算列表中的单词与数据库中的单词对应的次数。
使用随机单词的示例:
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)])
答案 0 :(得分:3)
您可以保留为每个项目更新的Map
个计数。由于您不希望在输入列表中包含不在数据库中的项目,如果我理解正确,
alter :: Ord k => (Maybe a -> Maybe a) -> k -> Map k a -> Map k a
是一个很好的方法。查找提供的密钥k
,如果它存在,则更新函数的参数将为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)
使用Functor
的{{1}}个实例。
然后生成的地图就是
Maybe
如果您想要列表而不是finalMap :: Map String Int
finalMap = foldl (flip $ alter incr) m0 $ snd input
,只需在Map
上致电assocs
或toList
。
答案 1 :(得分: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)]