我有一个包含字母的字符串,我希望确保它们在列表中的单词中。然而,运行它会导致它仍然留下包含不需要的字母的单词。
这是我的功能:
import Data.List
filterWords :: String -> [String]
filterWords str =
let strs = words str
letters = concat . words . nub $ "poultry outwits ants"
predicate = dropWhile (`elem` letters) ['a' .. 'z']
in dropWhile (any (`elem` predicate)) strs
我需要做些什么来改变这项工作?
为了说清楚,我想过滤掉任何包含不在“家禽狩猎蚂蚁”中的字母的单词,这意味着会删除像“年”这样的单词,因为尽管包含'y'
,'a'
,'r'
和's'
都满足谓词,它还包含'e'
,但不包含。{/ p>
答案 0 :(得分:4)
过滤事物列表(例如单词)的好方法是使用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")