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 は、データベース エントリが入力に現れる回数をカウントします。フォールドを使用したより良い実装に取り​​組んでいます。

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が検索され、存在する場合は更新関数への引数が検索され、存在しない場合は。Just valueになりますNothing。更新機能の結果がである場合Nothing、キーはから削除されますMap(または、存在しなかった場合は追加されません)。結果がである場合、キーは変更されたJust somethingに関連付けられます。somethingMap

したがって、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呼び出してください。assocstoListfinalMap

于 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 に答える