reversing default dict

  • Last Update :
  • Techknowledgy :

I believe the best way is to simply loop as you did:

target = defaultdict(list)
for key, values in original.items():
   for value in values:
   target[value].append(key)

Alternatively you could avoid the inner for:

for key, values in original.items():
   target.update(zip(values, [key] * len(values)))

Or using itertools.repeat:

import itertools as it

for key, values in original.items():
   target.update(zip(values, it.repeat(key)))

Is this more pythonic or just more cryptic?

map(lambda(i, k): x2[i].append(k), [(i, k) for i in v
   for k, v in x.items()
])

Following variant is required for python 3, and is less clear:

map(lambda i_k: x2[i_k[0]].append(i_k[1]), [(i, k) for i in v
   for k, v in x.items()
])

Suggestion : 2

Extend the left side of the deque by appending elements from iterable. Note, the series of left appends results in reversing the order of elements in the iterable argument.,When a letter is first encountered, it is missing from the mapping, so the default_factory function calls int() to supply a default count of zero. The increment operation then builds up the count for each letter.,The Counter class itself is a dictionary subclass with no restrictions on its keys and values. The values are intended to be numbers representing counts, but you could store anything in the value field.,The first argument provides the initial value for the default_factory attribute; it defaults to None. All remaining arguments are treated the same as if they were passed to the dict constructor, including keyword arguments.

import builtins
pylookup = ChainMap(locals(), globals(), vars(builtins))
import os, argparse

defaults = {
   'color': 'red',
   'user': 'guest'
}

parser = argparse.ArgumentParser()
parser.add_argument('-u', '--user')
parser.add_argument('-c', '--color')
namespace = parser.parse_args()
command_line_args = {
   k: v
   for k,
   v in vars(namespace).items() if v
}

combined = ChainMap(command_line_args, os.environ, defaults)
print(combined['color'])
print(combined['user'])
c = ChainMap() # Create root context
d = c.new_child() # Create nested child context
e = c.new_child() # Child of c, independent from d
e.maps[0] # Current context dictionary--like Python 's locals()
e.maps[-1] # Root context--like Python 's globals()
e.parents # Enclosing context chain--like Python 's nonlocals

d['x'] # Get first key in the chain of contexts
d['x'] = 1 # Set value in current context
del d['x'] # Delete from current context
list(d) # All nested values
k in d # Check all nested values
len(d) # Number of nested values
d.items() # All nested items
dict(d) # Flatten into a regular dictionary
class DeepChainMap(ChainMap):
   'Variant of ChainMap that allows direct updates to inner scopes'

def __setitem__(self, key, value):
   for mapping in self.maps:
   if key in mapping:
   mapping[key] = value
return
self.maps[0][key] = value

def __delitem__(self, key):
   for mapping in self.maps:
   if key in mapping:
   del mapping[key]
return
raise KeyError(key)

   >>>
   d = DeepChainMap({
      'zebra': 'black'
   }, {
      'elephant': 'blue'
   }, {
      'lion': 'yellow'
   }) >>>
   d['lion'] = 'orange'
# update an existing key two levels down
   >>>
   d['snake'] = 'red'
# new keys get added to the topmost dict
   >>>
   del d['elephant'] # remove an existing key one level down
DeepChainMap({
   'zebra': 'black',
   'snake': 'red'
}, {}, {
   'lion': 'orange'
})
>>> # Tally occurrences of words in a list >>>
   cnt = Counter() >>>
   for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
   ...cnt[word] += 1 >>>
   cnt
Counter({
      'blue': 3,
      'red': 2,
      'green': 1
   })

   >>>
   # Find the ten most common words in Hamlet >>>
   import re >>>
   words = re.findall(r '\w+', open('hamlet.txt').read().lower()) >>>
   Counter(words).most_common(10)[('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631),
      ('you', 554), ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)]
>>> c = Counter() # a new, empty counter >>>
   c = Counter('gallahad') # a new counter from an iterable >>>
   c = Counter({
      'red': 4,
      'blue': 2
   }) # a new counter from a mapping >>>
   c = Counter(cats = 4, dogs = 8) # a new counter from keyword args

Suggestion : 3

defaultdict objects support the following method in addition to the standard dict operations:,Extend the left side of the deque by appending elements from iterable. Note, the series of left appends results in reversing the order of elements in the iterable argument.,In addition to supporting the methods and operations of mappings, UserDict instances provide the following attribute:,In addition to supporting the methods and operations of mutable sequences, UserList instances provide the following attribute:

>>> baseline = {
      'music': 'bach',
      'art': 'rembrandt'
   } >>>
   adjustments = {
      'art': 'van gogh',
      'opera': 'carmen'
   } >>>
   list(ChainMap(adjustments, baseline))['music', 'art', 'opera']
>>> combined = baseline.copy() >>>
   combined.update(adjustments) >>>
   list(combined)['music', 'art', 'opera']
import builtins
pylookup = ChainMap(locals(), globals(), vars(builtins))
import os, argparse

defaults = {
   'color': 'red',
   'user': 'guest'
}

parser = argparse.ArgumentParser()
parser.add_argument('-u', '--user')
parser.add_argument('-c', '--color')
namespace = parser.parse_args()
command_line_args = {
   k: v
   for k,
   v in vars(namespace).items() if v is not None
}

combined = ChainMap(command_line_args, os.environ, defaults)
print(combined['color'])
print(combined['user'])
c = ChainMap() # Create root context
d = c.new_child() # Create nested child context
e = c.new_child() # Child of c, independent from d
e.maps[0] # Current context dictionary--like Python 's locals()
e.maps[-1] # Root context--like Python 's globals()
e.parents # Enclosing context chain--like Python 's nonlocals

d['x'] = 1 # Set value in current context
d['x'] # Get first key in the chain of contexts
del d['x'] # Delete from current context
list(d) # All nested values
k in d # Check all nested values
len(d) # Number of nested values
d.items() # All nested items
dict(d) # Flatten into a regular dictionary
class DeepChainMap(ChainMap):
   'Variant of ChainMap that allows direct updates to inner scopes'

def __setitem__(self, key, value):
   for mapping in self.maps:
   if key in mapping:
   mapping[key] = value
return
self.maps[0][key] = value

def __delitem__(self, key):
   for mapping in self.maps:
   if key in mapping:
   del mapping[key]
return
raise KeyError(key)

   >>>
   d = DeepChainMap({
      'zebra': 'black'
   }, {
      'elephant': 'blue'
   }, {
      'lion': 'yellow'
   }) >>>
   d['lion'] = 'orange'
# update an existing key two levels down
   >>>
   d['snake'] = 'red'
# new keys get added to the topmost dict
   >>>
   del d['elephant'] # remove an existing key one level down >>>
   d # display result
DeepChainMap({
   'zebra': 'black',
   'snake': 'red'
}, {}, {
   'lion': 'orange'
})