3

I have a list of dictionaries:

[
{"START":"Denver", "END":"Chicago", "Num":0},
{"START":"Dallas", "END":"Houston", "Num":3},
{"START":"Virginia", "END":"Boston", "Num":1},
{"START":"Washington", "END":"Maine", "Num":7}
]

How do I access the dictionary in this list that has "START":"Virginia", "END":"Boston" in most pythonic way?

alwbtc
  • 28,057
  • 62
  • 134
  • 188

4 Answers4

8

The most Pythonic way is probably a list comprehension:

[ d for d in dict_list if d["START"] == "Virginia" and d["END"] == "Boston" ]

As mgilson pointed out, if you are assuming that there's only one item in the list with that pair of locations, you can use next with the same generator expression, instead of the brackets. That will return just the matching dict, rather than a one-item list containing it:

trip = next( d for d in dict_list 
               if d["START"] == "Virginia" and d["END"] == "Boston" )

Either way, the result references the same dict object(s) as the original list, so you can make changes:

trip["Num"] = trip["Num"] + 1

And those changes will be there when accessed through the original list:

print(dict_list[2]["Num"])    # 2

As Ashwini Chaudhary indicated in his answer, your search may itself be specified as a dict. In that case, the if condition in the generator expression is a little different, but the logic is otherwise the same:

search = { "START": "Virginia", "END": "Boston" }
trip = next(d for d in dict_list if all(i in d.items() for i in search.items()))
Mark Reed
  • 91,912
  • 16
  • 138
  • 175
2

use all() with dict.items():

In [66]: lis=[                                      
   ....: {"START":"Denver", "END":"Chicago", "Num":0},
   ....: {"START":"Dallas", "END":"Houston", "Num":3},
   ....: {"START":"Virginia", "END":"Boston", "Num":1},
   ....: {"START":"Washington", "END":"Maine", "Num":7}
   ....: ]

In [67]: for x in lis:                              
   ....:         if all(y in x.items() for y in search.items()):
   ....:                 x['Num']="foobar"        #change Num here
   ....:         

In [68]: lis
Out[68]: 
[{'END': 'Chicago', 'Num': 0, 'START': 'Denver'},
 {'END': 'Houston', 'Num': 3, 'START': 'Dallas'},
 {'END': 'Boston', 'Num': 'foobar', 'START': 'Virginia'},
 {'END': 'Maine', 'Num': 7, 'START': 'Washington'}]

using a list comprehension:

In [58]: [x for x in lis if all(y in x.items() for y in search.items())]
Out[58]: [{'END': 'Boston', 'Num': 1, 'START': 'Virginia'}]
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
2

If you are going to do the search a lot of times and you know there is one and only one dict for every pair of locations you could create a dict from the list like this:

d = dict(((x['START'], x['END']), x) for x in list_of_dicts)

And then just do lookups in the new dict like this:

found_dict = d[('Virginia', 'Chicago')]

You could change found_dict then however you need.

Facundo Casco
  • 10,065
  • 8
  • 42
  • 63
1

If each item is unique, then you could do this:

def get_dict(items, start, end):
    for dict in items:
        if dict['START'] == start and dict['END'] == end:
            return dict

And then:

>>> items = [
    {"START":"Denver", "END":"Chicago", "Num":0},
    {"START":"Dallas", "END":"Houston", "Num":3},
    {"START":"Virginia", "END":"Boston", "Num":1},
    {"START":"Washington", "END":"Maine", "Num":7}
]
>>> get_dict(items, 'Virginia', 'Boston')
{"START":"Virginia", "END":"Boston", "Num":1}

It's fairly straightforward, but I thought I'd post it for the sake of completeness.

Michael0x2a
  • 58,192
  • 30
  • 175
  • 224