2
\$\begingroup\$

We can search for the list of dictionaries using the below some approaches, Can one please help me, which one is the memory efficient approach to use?

Provided that:

  • names are unique in the list
  • There will be definitely a name in each dictionary.

Where as:

items = [list_of_dicts]
name_to_b_searched = "some_name"

1 direct return from the for loop

def get_by_name(self, name_to_be_searched):
    for i in items:
        if i['name'] == name_to_be_searched:
              return i

2 Break from the for loop and return found dictionary

def get_by_name(self, name_to_be_searched):
    found = None
    for i in items:
        if i['name'] == name_to_be_searched:
              found = i
              break 
    return found

3 A generator function

def get_by_name(self, name_to_be_searched):
    for i in items:
        if i['name'] == name_to_be_searched:
              yield i

4 An inline generator

get_by_name =next(i for i in items if i['name'] == name_to_be_searched, None)

Sometimes I could have a huge csv records (in items), so was thinking which approach would be better to search a record. OR if there is any other approach you would recommend please let me know.

\$\endgroup\$
  • 4
    \$\begingroup\$ You did not define best. \$\endgroup\$ – Stephen Rauch Nov 19 '17 at 15:15
  • \$\begingroup\$ @StephenRauch - I did not get you \$\endgroup\$ – Laxmikant Nov 19 '17 at 17:01
  • 3
    \$\begingroup\$ You use the word best. This word has no specific technical meaning. \$\endgroup\$ – Stephen Rauch Nov 19 '17 at 17:03
  • \$\begingroup\$ Sadly, efficient is also technically ambiguous. \$\endgroup\$ – Stephen Rauch Nov 19 '17 at 17:09
  • 1
    \$\begingroup\$ Well, you could easily profile each piece of code you have and find out \$\endgroup\$ – Grajdeanu Alex. Nov 19 '17 at 17:20
4
\$\begingroup\$

None of the above.

OR if there is any other approach you would recommend please let me know.

The whole point of using dictionaries is that you don't need to search anything and can access everything in O(1) (on average) instead of the O(n) in all of your suggestions.

  • names are unique in the list
  • There will be definitely a name in each dictionary.

So, instead of using a list of dictionaries, use a dictionary of dictionaries using the name as the outer key.

Instead of

items = [{'name': 'a', 'age': 22, ...},
         {'name': 'b', 'age': 30, ...}]

you should have

items = {'a': {'age': 22, ...},
         'b': {'age': 30, ...}}

Now you can access each dictionary directly by using the name.

name = 'b'
print(items[name]['age'])
#  30

No loops, no searches, O(1) access.

\$\endgroup\$
  • \$\begingroup\$ I agree. However could you show how you could get such a dictionary? \$\endgroup\$ – Peilonrayz Nov 20 '17 at 15:53
  • \$\begingroup\$ @Peilonrayz dict_of_dicts = {d['name']: d for d in list_of_dictionaries} Sacrificing a single O(n) iteration for many O(1) lookups in the future. \$\endgroup\$ – DeepSpace Nov 20 '17 at 15:56
  • 1
    \$\begingroup\$ thanks, however I was meaning more to add it to your answer, :) \$\endgroup\$ – Peilonrayz Nov 20 '17 at 15:58
  • \$\begingroup\$ OP is worried about memory and you recommend to use faster lookup by doubling the amount of used memory? \$\endgroup\$ – 301_Moved_Permanently Nov 21 '17 at 13:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.