Reputation: 73
I'm working with a dictionary for an anagram program in Python. The keys are tuples of sorted letters, and the values are arrays of the possible words with those letters:
wordlist = {
('d', 'g', 'o'): ['dog', 'god'],
('a', 'c', 't'): ['act', 'cat'],
('a', 's', 't'): ['sat', 'tas'],
}
I am using regex to filter the list down. So given r't$'
as a filter the final result should be:
filtered_list = {
('a', 'c', 't'): ['act', 'cat'],
('a', 's', 't'): ['sat'],
}
So far I've gotten it down to two steps. First, keep all of the words that match the expression:
tmp = {k: [w for w in v if re.search(r't$', w)] for k, v in wordlist.items()}
This leaves me with empty lists:
{
('d', 'g', 'o'): [],
('a', 'c', 't'): ['act', 'cat'],
('a', 's', 't'): ['sat'],
}
Then I need a second pass to get rid of the empty lists:
filtered_list = {k: v for k, v in tmp.items() if v}
I'm sure there is a way to do these in one step, but I haven't figured it out yet. Is there a way to combine them? Or a better way to do this in general?
Upvotes: 7
Views: 175
Reputation: 2532
For a one-liner, something like this?
A = {k:[w for w in v if re.search(r't$', w)] for k,v in wordlist.items() if any(re.search(r't$', w) for w in v)}
Upvotes: 4
Reputation: 64318
Doing this in two steps is fine, and probably good for readability.
But to answer your question, here's a one-liner (broken into multiple lines, for readability). It uses a generator expression for generating the pairs from the first step.
{
k:v for k, v in
(
(kk, [w for w in vv if re.search(r't$', w)])
for kk, vv in wordlist.items()
)
if v
}
=> {('a', 'c', 't'): ['act', 'cat'], ('a', 's', 't'): ['sat']}
Upvotes: 4