単語をアナグラムでグループ化する Haskell 関数を作成しました。OCaml を学ぼうとしていますが、OCaml でパターン マッチングを使用する方法について少し混乱しています。誰かがこれをOCamlに翻訳するのを手伝ってくれませんか? ありがとうございました!
この関数は文字列のリストを受け取り、アナグラムでグループ化された文字列リストのリストに分割します。
import Data.List
groupByAnagrams :: [String] -> [[String]]
groupByAnagrams [] = []
groupByAnagrams (x:xs) = let (listOfAnagrams, listOfNonAnagrams) = (partitionByAnagrams (sort x) xs)
in
(x:listOfAnagrams):(groupByAnagrams listOfNonAnagrams)
このヘルパー関数は、並べ替えられた文字列sortedStr
と文字列のリストを取ります (文字列が並べ替えられているのは、反復ごとに並べ替えを呼び出す必要がないためです)。文字列リストは 2 つのリストに分割されます。1 つは と のアナグラムである文字列で構成され、もう 1 つsortedStr
はそうでない文字列で構成されます。この関数は、これら 2 つのリストで構成されるタプルを返します。
partitionByAnagrams :: String -> [String] -> ([String], [String])
partitionByAnagrams sortedStr [] = ([], [])
partitionByAnagrams sortedStr (x:xs)
| (sortedStr == (sort x)) = let (listOfAnagrams, listOfNonAnagrams) = (partitionByAnagrams sortedStr xs)
in
(x:listOfAnagrams, listOfNonAnagrams)
| otherwise = let (listOfAnagrams, listOfNonAnagrams) = (partitionByAnagrams sortedStr xs)
in
(listOfAnagrams, x:listOfNonAnagrams)
これは単なるテストケースです:
test1 = mapM_ print (groupByAnagrams ["opts", "alerting", "arrest", "bares", "drapes", "drawer", "emits", "least", "mate", "mates", "merit", "notes", "palest", "parses", "pores", "pots", "altering", "rarest", "baser", "parsed", "redraw", "items", "slate", "meat", "meats", "miter", "onset", "pastel", "passer", "poser", "spot", "integral", "raster", "bears", "rasped", "reward", "mites", "stale", "meta", "steam", "mitre", "steno", "petals", "spares", "prose", "stop", "relating", "raters", "braes", "spared", "warder", "smite", "steal", "tame", "tames", "remit", "stone", "plates", "sparse", "ropes", "tops", "triangle", "starer", "saber", "spread", "warred", "times", "tales", "team", "teams", "timer", "tones", "staple", "spears", "spore"])
**編集!!!これは私の関数の書き直されたバージョンです。非効率性を指摘してくれた jrouquie に感謝します。** 10/7 に再度編集 - わかりやすくするためにタプルでパターン マッチングを使用しました。これらすべての fst と snd は必要ありません。
groupByAnagrams2 :: [String] -> [[String]]
groupByAnagrams2 str = groupBySnd $ map (\s -> (s, (sort s))) str
groupBySnd :: [(String, String)] -> [[String]]
groupBySnd [] = []
groupBySnd ((s1,s2):xs) = let (listOfAnagrams, listOfNonAnagramPairs) = (partitionBySnd s2 xs)
in
(s1:listOfAnagrams):(groupBySnd listOfNonAnagramPairs)
partitionBySnd :: String -> [(String, String)] -> ([String], [(String, String)])
partitionBySnd sortedStr [] = ([], [])
partitionBySnd sortedStr ((s, sSorted):ss)
| (sortedStr == sSorted) = let (listOfAnagrams, listOfNonAnagramPairs) = (partitionBySnd sortedStr ss)
in
(s:listOfAnagrams, listOfNonAnagramPairs)
| otherwise = let (listOfAnagrams, listOfNonAnagramPairs) = (partitionBySnd sortedStr ss)
in
(listOfAnagrams, (s, sSorted):listOfNonAnagramPairs)