Question

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?

Was it helpful?

Solution

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']}

OTHER TIPS

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)}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top