过滤列表(例如单词)的好方法是使用
filter
函数。您需要提供一个谓词,告诉它哪些字符串应该包含在内。您评论说想要包括那些由字母组成的字符串
"poultry outwits ants"
,那么就可以这样做:
filterWords :: String -> [String]
filterWords str = filter acceptableWord (words str)
where
acceptableWord = all (`elem` "poultry outwits ants")
现在,根据你在另一条评论中的写法:
“有些单词中相同字母的数量比原始单词中的数量多。”
因此,我怀疑你实际上想知道哪些单词可以由“poultry outwits ants”中的字母组成。
为了做到这一点,您可以计算给定单词(以及mgic字符串“poultry outwits ants”)中每个字符出现的频率,然后验证不仅单词中的每个字母都出现在魔术字符串中,而且该字母在魔术字符串中出现的次数也不超过单词中的次数。
我建议首先定义一个函数来计算“字符频率表”,即它计算给定字符串中每个字符出现的次数:
freq :: String -> [(Char, Int)]
freq = map (\s -> (head s, length s)) . group . sort
此外,我会定义一个函数来判断一个频率表
x
是否为另一个表
y
的"子集",也就是验证每个在
x
中的字符是否也出现在
y
中,但不会出现更多次:
subset :: [(Char, Int)] -> [(Char, Int)] -> Bool
subset x y = all f x
where
f (ch, occ) = case lookup ch y of
Just occ' -> occ <= occ'
Nothing -> False
您可以使用这个方法来定义
acceptableWord
,以便它只接受其频率表是魔术字符串的频率表的子集的单词,因此我们得到:
filterWords :: String -> [String]
filterWords str = filter acceptableWord (words str)
where
acceptableWord w = subset (freq w) (freq "poultry outwits ants")
letters :: Data.Set Char
,而不是一个列表吗? - Bartek Banachewicz