Converting a list of lists to a dictionary and calling values using a for loop

Question:

I have a list of single-element lists:

geos = [["'latitude': 12.1234, 'longitude': -12.1234, 'accuracy': 100"],
        ["'latitude': 12.1233, 'longitude': -12.1233, 'accuracy': 100"],
        ["'latitude': 12.1222, 'longitude': -12.1111, 'accuracy': 100"],
        ["'latitude': 12.1111, 'longitude': -12.1222, 'accuracy': 100"]]

I’ve acquired the data in this format from elsewhere. What I’d like to achieve from here is converting this list of lists into a dictionary so that I can pass in the correct parameters relevant to my for loop. This is where I’m at so far:

geos_dict = {geo[0]:None for geo in geos}

for i, geos_dict in enumerate(geos_dict):
     options = ChromeOptions()
     options.add_argument("--headless")
     driver = webdriver.Chrome(service=Service('/Library/path/chromedriver'))
     driver.execute_cdp_cmd("Browser.grantPermissions", {"origin": 
               "https://www.google.com","permissions": ["geolocation"]})
     #This is the line where the error is occurring   
     driver.execute_cdp_cmd("Emulation.setGeolocationOverride", 
            {"latitude": geo["latitude"], "longitude": 
            geo["longitude"], "accuracy": geo["accuracy"]})
     driver.get("https://www.google.com")

I’m returning an error: TypeError: list indices must be integers or slices, not str

Obviously, I’m not doing this right. But I don’t know enough about converting lists to dictionaries and calling values from the key:value pair.

How can I do this?

Asked By: VRapport

||

Answers:

Might be a bit slow but you want something like this

import re
parser = re.compile("'latitude': (.*), 'longitude': (.*), 'accuracy': (.*)")

for geo in geos:
   match = parser.match(geo[0])
   # in match object will be 3 groups
   lat, long, acc = match.groups()
   geo_dict = {'latitude': lat, 'longitude': long, 'accuracy' : acc}

   ... #
   driver.execute_cdp_cmd("Emulation.setGeolocationOverride", geo_dict)

Answered By: Daraan

Each element in your list is a single-element list, and that single element is a string. That string represents a dictionary, minus the opening and closing curly braces. ast.literal_eval provides a safe way to parse literal data structures like this.

Also: you say you want to convert geos into a dictionary, and your code does so, but what you must actually want is a list of dictionaries to then loop over.

from ast import literal_eval
from pprint import pprint

geos = [["'latitude': 12.1234, 'longitude': -12.1234, 'accuracy': 100"],
        ["'latitude': 12.1233, 'longitude': -12.1233, 'accuracy': 100"],
        ["'latitude': 12.1222, 'longitude': -12.1111, 'accuracy': 100"],
        ["'latitude': 12.1111, 'longitude': -12.1222, 'accuracy': 100"]]

geos = [literal_eval(f'{{{geo[0]}}}') for geo in geos]

pprint(geos, sort_dicts=False)

Output (using pprint to more easily see the nested structure):

[{'latitude': 12.1234, 'longitude': -12.1234, 'accuracy': 100},
 {'latitude': 12.1233, 'longitude': -12.1233, 'accuracy': 100},
 {'latitude': 12.1222, 'longitude': -12.1111, 'accuracy': 100},
 {'latitude': 12.1111, 'longitude': -12.1222, 'accuracy': 100}]

That’s a formatted string literal or "f-string", by the way. You can include variables or other expressions inside such a string with {}, and you can escape, that is, include a literal {, with {{. So all that f-string does is put {} around each string to make it a valid representation of a dictionary.

Answered By: CrazyChucky
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.