194

I've got a Python list of dictionaries as follows:

a = [
    {'main_color': 'red', 'second_color':'blue'},
    {'main_color': 'yellow', 'second_color':'green'},
    {'main_color': 'yellow', 'second_color':'blue'},
]

I'd like to check whether a dictionary with a particular key/value already exists in the list as follows:

// is a dict with 'main_color'='red' in the list already?
// if not: add item
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
AP257
  • 89,519
  • 86
  • 202
  • 261

8 Answers8

406

Here's one way to do it:

if not any(d['main_color'] == 'red' for d in a):
    # does not exist

The part in parentheses is a generator expression that returns True for each dictionary that has the key-value pair you are looking for, otherwise False.


If the key could also be missing the above code can give you a KeyError. You can fix this by using get and providing a default value. If you don't provide a default value, None is returned.

if not any(d.get('main_color', default_value) == 'red' for d in a):
    # does not exist
Aditya Shaw
  • 323
  • 4
  • 11
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • 1
    Amazing one-liner syntax, I have been look so hard for this! I am curious that where in the Python docs that shows us we can actually put the operation of 'for' before the 'for' ? – sylye May 11 '17 at 11:26
  • 2
    I found it, it's called List Comprehensions https://docs.python.org/2/whatsnew/2.0.html?highlight=comprehensions – sylye May 12 '17 at 10:01
  • 3
    Is there a possibility to test if `'main_color': 'red'` AND `'second_color':'blue'` exist ? – Florent May 07 '18 at 23:19
  • 2
    Is there a way, once the expression has evaluated to true or false, to perform an action on the value without having to loop again? – Bryce Jun 13 '18 at 15:06
  • its not working when data comes with "null" [{"main_color":null,"second_color":"red"}, {"main_color:"green","second_color":"null"}] – Ashok Sri Sep 05 '19 at 12:53
  • @Bryce If it's not that many elements, you could do something like `matchingElements = [d for d in a if d.get('main_color', default_value) == 'red']; if (len(matchingElements)): doSomething(matchingElements[0])` – Nicolai Weitkemper Oct 28 '20 at 22:49
  • If it happens inside an iteration wouldn't it be inefficient? And a better way would be to first create a data type with all the values and then check without iteration if the value is there, instead of iteration for every iteration – Niklas Rosencrantz Nov 27 '21 at 13:58
8

Maybe this helps:

a = [{ 'main_color': 'red', 'second_color':'blue'},
     { 'main_color': 'yellow', 'second_color':'green'},
     { 'main_color': 'yellow', 'second_color':'blue'}]

def in_dictlist(key, value, my_dictlist):
    for entry in my_dictlist:
        if entry[key] == value:
            return entry
    return {}

print in_dictlist('main_color','red', a)
print in_dictlist('main_color','pink', a)
Dawoodjee
  • 439
  • 5
  • 16
Tony Veijalainen
  • 5,447
  • 23
  • 31
7

Based on @Mark Byers great answer, and following @Florent question, just to indicate that it will also work with 2 conditions on list of dics with more than 2 keys:

names = []
names.append({'first': 'Nil', 'last': 'Elliot', 'suffix': 'III'})
names.append({'first': 'Max', 'last': 'Sam', 'suffix': 'IX'})
names.append({'first': 'Anthony', 'last': 'Mark', 'suffix': 'IX'})

if not any(d['first'] == 'Anthony' and d['last'] == 'Mark' for d in names):

    print('Not exists!')
else:
    print('Exists!')

Result:

Exists!
Amitsas1
  • 103
  • 1
  • 7
4

Perhaps a function along these lines is what you're after:

 def add_unique_to_dict_list(dict_list, key, value):
  for d in dict_list:
     if key in d:
        return d[key]

  dict_list.append({ key: value })
  return value
Cameron
  • 96,106
  • 25
  • 196
  • 225
4

Just another way to do what the OP asked:

 if not filter(lambda d: d['main_color'] == 'red', a):
     print('Item does not exist')

filter would filter down the list to the item that OP is testing for. The if condition then asks the question, "If this item is not there" then execute this block.

Gourav Chawla
  • 470
  • 1
  • 4
  • 12
  • 5
    I think this needs to be `if not list(filter(lambda d: d['main_color'] == 'red', a)):` to create a list object which the if then tests if it's empty or not. `filter(..)` as above creates a filter object which will always be true. – mark mcmurray Oct 25 '21 at 14:06
1

I think a check if the key exists would be a bit better, as some commenters asked under the preferred answer enter link description here

So, I would add a small if clause at the end of the line:


input_key = 'main_color'
input_value = 'red'

if not any(_dict[input_key] == input_value for _dict in a if input_key in _dict):
    print("not exist")

I'm not sure, if wrong but I think the OP asked to check, if the key-value pair exists and if not the key value pair should be added.

In this case, I would suggest a small function:

a = [{ 'main_color': 'red', 'second_color': 'blue'},
     { 'main_color': 'yellow', 'second_color': 'green'},
     { 'main_color': 'yellow', 'second_color': 'blue'}]

b = None

c = [{'second_color': 'blue'},
     {'second_color': 'green'}]

c = [{'main_color': 'yellow', 'second_color': 'blue'},
     {},
     {'second_color': 'green'},
     {}]


def in_dictlist(_key: str, _value :str, _dict_list = None):
    if _dict_list is None:
        # Initialize a new empty list
        # Because Input is None
        # And set the key value pair
        _dict_list = [{_key: _value}]
        return _dict_list

    # Check for keys in list
    for entry in _dict_list:
        # check if key with value exists
        if _key in entry and entry[_key] == _value:
            # if the pair exits continue
            continue
        else:
            # if not exists add the pair
            entry[_key] = _value
    return _dict_list


_a = in_dictlist("main_color", "red", a )
print(f"{_a=}")
_b = in_dictlist("main_color", "red", b )
print(f"{_b=}")
_c = in_dictlist("main_color", "red", c )
print(f"{_c=}")

Output:

_a=[{'main_color': 'red', 'second_color': 'blue'}, {'main_color': 'red', 'second_color': 'green'}, {'main_color': 'red', 'second_color': 'blue'}]
_b=[{'main_color': 'red'}]
_c=[{'main_color': 'red', 'second_color': 'blue'}, {'main_color': 'red'}, {'second_color': 'green', 'main_color': 'red'}, {'main_color': 'red'}]
Rene
  • 976
  • 1
  • 13
  • 25
1

There are 2 ways to check if a specific key's value exists in a list of dictionaries as shown below:

a = [
    {'main_color': 'red', 'second_color':'blue'},
    {'main_color': 'yellow', 'second_color':'green'},
    {'main_color': 'yellow', 'second_color':'blue'}
]

# The 1st way
print(any(dict['main_color'] == 'red' for dict in a)) # True
print(any(dict['main_color'] == 'green' for dict in a)) # False

# The 2nd way
print(any('red' == dict['main_color'] for dict in a)) # True
print(any('green' == dict['main_color'] for dict in a)) # False

In addition, this code below can check if a value exists in a list of dictionaries:

print(any('red' in dict.values() for dict in a)) # True
print(any('green' in dict.values() for dict in a)) # True
print(any('black' in dict.values() for dict in a)) # False
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
0

Following works out for me.

    #!/usr/bin/env python
    a = [{ 'main_color': 'red', 'second_color':'blue'},
    { 'main_color': 'yellow', 'second_color':'green'},
    { 'main_color': 'yellow', 'second_color':'blue'}]

    found_event = next(
            filter(
                lambda x: x['main_color'] == 'red',
                a
            ),
      #return this dict when not found
            dict(
                name='red',
                value='{}'
            )
        )

    if found_event:
        print(found_event)

    $python  /tmp/x
    {'main_color': 'red', 'second_color': 'blue'}
samtoddler
  • 8,463
  • 2
  • 26
  • 21