4

If I have a file that contains these dictionaries:

{
    "dict1" : {
        "data1" : "a",
        "data2" : "b",
        "data3" : "c",
        "data4" : "d",
        "data5" : "e"
    },
    "dict2" : {
        "data1" : "f",
        "data2" : "g",
        "data3" : "h",
        "data4" : "i",
        "data5" : "j"
    }

How would I go about accessing every dictionary key "data3". Such that the output would be:

c, h

Because there are multiple dictionaries inside the file I won't know the names. Is there anyway to iterate over them to pull out those keys?

Chad
  • 118
  • 8
  • Other than using `for`? – Ignacio Vazquez-Abrams Apr 29 '16 at 21:11
  • What names don't you know? The keys of the outer dict containing the inner dicts ("dict1" and "dict2" in your example)? – das-g Apr 29 '16 at 21:14
  • I'm loading this from a file which I have defined as self.players, I'm trying these methods but I'm not having much success. Is it an absolute must to create a name for the dictionaries like below? I.E. dct = .... and your_dict = ... ? – Chad Apr 29 '16 at 21:35

5 Answers5

5
>>> ', '.join(subdict['data3'] for subdict in maindict.values())
'c, h'

Explanation:

Your data is a dictionary maindict, where the keys are 'dict1' and 'dict2'.

>>> for key in maindict.keys():
...     print key
dict1
dict2

We're not interested in the keys, but want the values (which are actually two more dictionaries):

>>> for value in maindict.values():
...     print value
{"data1" : "a",
 "data2" : "b",
 "data3" : "c",
 "data4" : "d",
 "data5" : "e"}
{"data1" : "f",
 "data2" : "g",
 "data3" : "h",
 "data4" : "i",
 "data5" : "j"}

To get the value in the sub-dictionary corresponding to key 'data3':

>>> for subdict in maindict.values():
...     print subdict['data3']
c
h

You said you wanted a comma separated result. str.join allows you to join a sequence of strings using other characters as a separator:

>>> ', '.join(['William', 'Shatner', 'Speaks', 'Like', 'This'])
'William, Shatner, Speaks, Like, This'

The final piece of the puzzle is that we can generate sequences on the fly using a generator expression to create a generator:

>>> results = (subdict['data3'] for subdict in maindict.values())
>>> results
<generator object <genexpr> at 0x03115710>

You can pass a generator anywhere a sequence is expected:

>>> list(results)
['c', 'h']

So, we use a generator expression with str.join:

>>> ', '.join(subdict['data3'] for subdict in maindict.values())
'c, h'
Peter Wood
  • 23,859
  • 5
  • 60
  • 99
  • This worked. But I'm not really sure how. Can you explain it to me? Edit: also Thank you!!! – Chad Apr 29 '16 at 21:49
  • 1
    Explanation added, sorry it's a bit long, and sorry the original answer was a bit short (c: – Peter Wood Apr 30 '16 at 05:52
  • No! The explanation was perfect. I was able to follow it and I think I took away a better understanding of generator expressions and str.join. I plan to comment my code and provide a link to this answer for others to read. Thanks again!! – Chad Apr 30 '16 at 14:50
  • is there a way to do this such that you do not have to hard-code `'data3'` and can expand it to iterate over all existing keys in the subdicts? I've been trying multiple different kinds of `for` loops but can't get it to work – user5359531 Oct 25 '16 at 17:24
  • 1
    @user5359531 I'm not sure I understand. You're probably best trying to formulate it as a new question with inputs, desired outputs, actual outputs and what you've tried. Then you'll have the whole of Stack Overflow working on your question instead of just little old me. – Peter Wood Oct 25 '16 at 21:08
1

Assuming the dictionaries are only nested once like in your example, you can use a simple list comprehension, like this:

dct = [v["data3"] for v in oridict.values()]

This loops through your original dict (oridict), storing the values into v, which should be another dict, and then for every value v in the original dict, it gets the value of "data3".

Natecat
  • 2,175
  • 1
  • 17
  • 20
1

Assuming you have your dict like this (you forgot a closing }):

dct = {
    "dict1" : {
        "data1" : "a",
        "data2" : "b",
        "data3" : "c",
        "data4" : "d",
        "data5" : "e"
    },
    "dict2" : {
        "data1" : "f",
        "data2" : "g",
        "data3" : "h",
        "data4" : "i",
        "data5" : "j"}
    }

Just use a generator expression:

>>> i_key = 'data3' # inner key
>>> for value in (dct[o_key][i_key] for o_key in dct if i_key in dct[o_key]):
...     print(value)
h
c

This will only print the data3 value if it exists in the nested dictionary otherwise it is simply skipped.

MSeifert
  • 145,886
  • 38
  • 333
  • 352
1

So, if I understand correctly, "dict1" and "dict2" are unknown names, and of unknown quantity, but each of them have a "data3" that you would like to get the value of? (by the way, "data3" is the key, c and h are the values).

To do this, lets assume the whole thing has been read in and is stored in, say, all_data. If you don't know how to do this, I suggest looking at the json module, as this is basically in json format.

for k,v in all_data.items():
    # v will now hold the sub-dictionary, so we can just grab "data3":
    print v.get('data3',"")  # I used the .get() method incase "data3" doesn't exist
brettb
  • 771
  • 1
  • 6
  • 14
-1

You can also use this code:

TargetKey= 'data3'
output = map(lambda D:S[D].get(TargetKey, ''), S )
', '.join(output) # or simply loop throw output
nino_701
  • 672
  • 3
  • 13
  • 2
    This code is very unpythonic, it breaks pep8 in like 5 places, and uses [map](http://stackoverflow.com/a/10973817/1357527) instead of a list comprehension – Natecat Apr 30 '16 at 05:07