1

I came across this issue in Python 3.x recently, and as I couldn't find a solution, I am looking for some clarification on how to solve it properly.

list_of_dicts = [dict_a, dict_b]
dict_a = {"id": 123, "foo": "bar"}
...

Based on list of dicts I want to create another list.

This list should contain objects of some sort, that I will then use to do something, in my case bulk write to a database, this works as expected:

operations = [ Object(arg = {"id": doc["id"]}) for doc in list_of_dicts ]
write_to_db(operations)

My issue is the following: in certain instances, I want to add further key value pairs to the arg dictionary:

further_keys = ["foo"]
operations = [ Object(arg = {"id": doc["id"]}.update({i:doc[i] for i in further_keys}))
               for doc in list_of_dicts ]

Unfortunately this fails as "doc" is not assigned in the context of the dict comp

Question is if it is possible to somehow set the scope to the list comprehension?

I am not the most advanced coder, so happy for any valuable input here

Thanks!

Edit

Thanks, it's so simple actually, no idea why I was thinking to use "update" in this case. Here a minimal working sample:

import pymongo

data = [{"id":1, "map": "DE", "date":"today"}, 
        {"id":2, "map": "FR", "date":"tomorrow"},
        {"id":3, "map": "IT", "date":"yesterday"}]

additional_keys = ["map"]
standard_key = ["id"]
key_tuple = tuple(standard_key + additional_keys)

operations = [ pymongo.operations.ReplaceOne(
               filter={key:doc[key] for key in key_tuple}, 
               replacement=doc, 
               upsert=True) 
               for doc in data ]

Which - as desired - produces:

[ReplaceOne({'id': 1, 'map': 'DE'}, {'id': 1, 'map': 'DE', 'date': 
 'today'}, True, None),
 ReplaceOne({'id': 2, 'map': 'FR'}, {'id': 2, 'map': 'FR', 'date': 
 'tomorrow'}, True, None),
 ReplaceOne({'id': 3, 'map': 'IT'}, {'id': 3, 'map': 'IT', 'date': 
 'yesterday'}, True, None)]

Thank y'all very much. I will in the future produce a minimal working sample right away!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

1 Answers1

0

You can use dictionary comprehension inside the list comprehension. Using this answer, you can construct the following:

operations = [ Object(args = {key:doc[key] for key in ("id", "name", "other key") } ) for doc in list_of_dicts ]

Wrote this mobile so haven't tested, but you can fill that tuple with the further keys you want to add to args=

dwb
  • 2,136
  • 13
  • 27
  • this is not necessary, the OPs code should work without an error (although it isn't doing what the OP seems to thinkit is doing) – juanpa.arrivillaga Aug 02 '20 at 23:09
  • The OP's code doesn't work, but as you said its not from the error they're describing. Even though they mis-interpreted the reason for failure, I think we can still clearly see why its failed and provide a working alternative. – dwb Aug 02 '20 at 23:13