-1

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?

petezurich
  • 9,280
  • 9
  • 43
  • 57
VRapport
  • 61
  • 1
  • 7
  • What is your question? – Talha Tayyab Jan 15 '23 at 19:02
  • My question is how do I convert the list to a dictionary and pass the correct parameters to 'latitude', 'longitude', and 'accuracy' – VRapport Jan 15 '23 at 19:06
  • 1
    We don't really need the whole first part of this for a complete [mre] if all you're looking to do is convert the intermediate result (the list of lists) to a list of dictionarties. – CrazyChucky Jan 15 '23 at 19:15

2 Answers2

2

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.

CrazyChucky
  • 3,263
  • 4
  • 11
  • 25
  • If you want to make the output a dictionary, simply add an index in a dictionary comprehension: d = {i: literal_eval(f'{{{g[0]}}}') for i, g in enumerate(geos)} And the output from that is: {0: {'latitude': 12.1234, 'longitude': -12.1234, 'accuracy': 100}, 1: {'latitude': 12.1233, 'longitude': -12.1233, 'accuracy': 100}, 2: {'latitude': 12.1222, 'longitude': -12.1111, 'accuracy': 100}, 3: {'latitude': 12.1111, 'longitude': -12.1222, 'accuracy': 100}} – Carlos Melus Jan 15 '23 at 19:31
  • @CarlosMelus That's nearly impossible to read. Please at least put back ticks around code in comments to code-format it, or better yet post your own answer where you can use newlines and syntax highlighting. That said, from the code shown trying to *use* the result, I don't think a dictionary makes any sense for the asker's purpose. – CrazyChucky Jan 15 '23 at 19:33
  • Sorry about the formatting, I agree it does not look nice. I didn't want to simply leverage your answer and wanted to give you credit for it (`literal_eval` is awesome in this scenario). Also, the OP is asking for a dictionary as the output, whether we think it makes sense or not. That is why I proposed that solution, and making the indices match the original list just in case. – Carlos Melus Jan 15 '23 at 20:03
1

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)

Daraan
  • 1,797
  • 13
  • 24