10

if i have a simple list objects:

shapes = [
  {
    'shape': 'square',
    'width': 40,
    'height': 40
  },
  {
    'shape': 'rectangle',
    'width': 30,
    'height': 40

  }
]

How can i quickly check if a shape with value square exists? I know I can use a for loop to check each object, but is there a faster way?

Thanks in advance!

2
  • 6
    any(shape.get('shape') == 'square' for shape in shapes) Commented Sep 10, 2017 at 2:11
  • Why do you assume that a for loop is slow? Commented Sep 10, 2017 at 3:39

6 Answers 6

24

You can do this in one line with the builtin function any:

if any(obj['shape'] == 'square' for obj in shapes):
    print('There is a square')

This is equivalent to the for-loop approach, though.


If you need to get the index instead, then there is still a one-liner that can do this without sacrificing efficiency:

index = next((i for i, obj in enumerate(shapes) if obj['shape'] == 'square'), -1)

However, this is complicated enough that it's probably better to just stick with a normal for loop.

index = -1
for i, obj in enumerate(shapes):
    if obj['shape'] == 'square':
        index = i
        break
Sign up to request clarification or add additional context in comments.

1 Comment

perfect! following that approach, is there a way to quickly return the index of that shape as well?
8

Look ma, no loop.

import json
import re

if re.search('"shape": "square"', json.dumps(shapes), re.M):
    ... # "square" does exist

If you want to retrieve the index associated with square, you'd need to iterate over it using for...else:

for i, d in enumerate(shapes):
    if d['shape'] == 'square':
        break
else:
    i = -1

print(i) 

Performance

100000 loops, best of 3: 10.5 µs per loop   # regex
1000000 loops, best of 3: 341 ns per loop   # loop

7 Comments

How is the performance here ? Can you please provide performance comparison with the for loop solution
@SarathSadasivanPillai Oh, there's absolutely no comparison. A loop is by far faster than a regex. I think OP accepted my answer because of the second part of my answer, not the first.
Test mine, test mine - 'square' in map(operator.itemgetter('shape'), shapes)
Different machine/cpu/speed --> apples and oranges. Thankyouverymuch.
Although simple, this solution throws an error with any non-JSON serializable objects. Even when the objects are serializable, it can be hacked: repl.it/KtXT/0
|
3

Using list comprehension you can do:

if [item for item in shapes if item['shape'] == 'square']:
    # do something

Using filter():

if list(filter(lambda item: item['shape'] == 'square', shapes)):
    # do something

Comments

1

You can try this, using get for a more robust solution:

if any(i.get("shape", "none") == "square" for i in shapes):
    #do something
    pass

Comments

1

Checking only if it exists:

any(shape.get('shape') == 'square' for shape in shapes)

Getting first index (you will get StopIteration exception if it does not exist).

next(i for i, shape in enumerate(shapes) if shape.get('shape') == 'square')

All indexes:

[i for i, shape in enumerate(shapes) if shape.get('shape') == 'square']

Comments

1
import operator
shape = operator.itemgetter('shape')
shapez = map(shape, shapes)
print('square' in shapez)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.