Dictionary of dictionary - Get 2nd keys I have a dictionary of dictionary such as d below, and I would like to get the list of all keys but not on the first level (i.e. ABC, DEF) but the one at the second level (i.e 0 and 1 for ABC ; 1 and 2 for DEF...)

I got this small code that does the job by reading all the dictionaries and by saving the keys (of second level):

d = {
    'ABC' : {'0' : [(1,0.5), (2, 0.25)], '1' : [(1,0.4), (3,0.35)]},
    'DEF' : {'1' : [(1,0.5), (4, 0.15)], '2' : [(2,0.3), (3,0.25)]},
    'GHI' : {'0' : [(3,0.2), (4, 0.05)], '2' : [(2,0.2), (2,0.25)]},
}

keys2 = []
for small_d in d.itervalues():
    keys2.extend(small_d.keys())

print set(keys2)
# set(['1', '0', '2'])


But I'm sure there is a more pythonic way to do it (and more efficient), any ideas?
Yes, there's a shorter (pythonic) way to do this using set comprehensions:

d = {
    'ABC' : {'0' : [(1,0.5), (2, 0.25)], '1' : [(1,0.4), (3,0.35)]},
    'DEF' : {'1' : [(1,0.5), (4, 0.15)], '2' : [(2,0.3), (3,0.25)]},
    'GHI' : {'0' : [(3,0.2), (4, 0.05)], '2' : [(2,0.2), (2,0.25)]},
}
print {j for i in d.itervalues() for j in i}
# set(['1', '0', '2'])


Then if you just want a list object you can use list() to convert the set to list.



More, in your example you could just make keys2 a set to begin with and call keys2.add instead of extend.



And some benchmarks from your solution, mine and other answers:

import timeit
from itertools import chain


def m1(d):
    return {j for i in d.itervalues() for j in i}


def m2(d):
    keys2 = []
    for small_d in d.itervalues():
        keys2.extend(small_d.keys())

    return set(keys2)


def m3(d):
    return set(chain.from_iterable(d.itervalues()))


def m4(d):
    keys2 = set([])
    for small_d in d.itervalues():
        keys2.update(small_d.keys())
    return keys2


d = {
    'ABC': {'0': [(1, 0.5), (2, 0.25)], '1': [(1, 0.4), (3, 0.35)]},
    'DEF': {'1': [(1, 0.5), (4, 0.15)], '2': [(2, 0.3), (3, 0.25)]},
    'GHI': {'0': [(3, 0.2), (4, 0.05)], '2': [(2, 0.2), (2, 0.25)]},
}

print(timeit.timeit(setup='from __main__ import m1, d', number=100000000))
print(timeit.timeit(setup='from __main__ import m2, d', number=100000000))
print(timeit.timeit(setup='from __main__ import m3, d', number=100000000))
print(timeit.timeit(setup='from __main__ import m4, d', number=100000000))





0.00136395591689003
0.0012866411345431158
0.0011429587956683193
0.0011374851827588035