jv95
jv95

Reputation: 691

Optimize code with dictionary comprehension

I am trying to optimize my code and I found out about comprehensions. But I am struggling with my code and how to apply dictionary comprehension. The original code is below.

How do I optimize this code in a proper pythonic way?

all_users = []
for x in range(len(result)):
    user = {}
    user["fieldy"] = str(result[x][1].get("valueforfield1", None))[3:-2]
    user["fieldx"] = str(result[x][1].get("valueforfield2", None))[3:-2]
    user["fieldc"] = str(result[x][1].get("valueforfield3", None))[3:-2]
    user["fieldv"] = str(result[x][1].get("valueforfield4", None))[3:-2]
    user["fieldb"] = str(result[x][1].get("valueforfield5", None))[3:-2]
    all_users.append(user)

example value of result

result = [('CN=Xxx X,OU=X,OU=X,DC=X,DC=X', {'valueforfield1': [b'Va'], 'valueforfield2': [b'val'], 'valueforfield3': [b'+123'], 'valueforfield4': [b'[email protected]'], 'valueforfield5': [b'examplevalue']}),('CN=Yyy Y,OU=Y,OU=Y,DC=Y,DC=Y', {'valueforfield1': [b'Ycx'], 'valueforfield2': [b'Dy'], 'valueforfield3': [b'+321'], 'valueforfield4': [b'[email protected]'], 'valueforfield5': [b'examplevaluey']})]

after the code is executed the user dictionary have following content after the first iteration of for loop

{"fieldy": "Va", "fieldx": "val", "fieldc": "+123", "fieldv": "[email protected]", "fieldb": "examplevalue"}

Also should I write a function to replace the user["field1"] = str(result[x][1].get("valueforfield1", None))[3:-2] code? Is it worth it and recommended? Thanks!

Upvotes: 0

Views: 259

Answers (2)

RomanPerekhrest
RomanPerekhrest

Reputation: 92854

With well-factored approach:

result = [('CN=Xxx X,OU=X,OU=X,DC=X,DC=X',
           {'valueforfield1': [b'Va'], 'valueforfield2': [b'val'], 'valueforfield3': [b'+123'],
            'valueforfield3': [b'[email protected]'], 'valueforfield5': [b'examplevalue']}),
          ('CN=Yyy Y,OU=Y,OU=Y,DC=Y,DC=Y',
           {'valueforfield1': [b'Ycx'], 'valueforfield2': [b'Dy'],
            'valueforfield3': [b'+321'], 'valueforfield3': [b'[email protected]'],
            'valueforfield5': [b'examplevaluey']})]

def compose_user_details(data):
    keys_map = {"fieldy": "valueforfield1", "fieldx": "valueforfield2",
                "fieldc": "valueforfield3", "fieldv": "valueforfield4",
                "fieldb": "valueforfield5", "fieldn": "valueforfield6",
                }
    user_details = []

    for i in range(len(result)):
        dataset = result[i][1]  # getting the needed `data source` at once
        user_details.append({k: str(dataset.get(v, None))[3:-2]
                             for k,v in keys_map.items()})
    return user_details

print(compose_user_details(result))

The output:

[{'fieldy': 'Va', 'fieldx': 'val', 'fieldc': '[email protected]', 'fieldv': '', 'fieldb': 'examplevalue', 'fieldn': ''}, {'fieldy': 'Ycx', 'fieldx': 'Dy', 'fieldc': '[email protected]', 'fieldv': '', 'fieldb': 'examplevaluey', 'fieldn': ''}]

Upvotes: 1

Green Cloak Guy
Green Cloak Guy

Reputation: 24691

Using just a dict comprehension to take care of the repeating code:

all_users = []
for x in range(len(result)):
    user = {f"field{i}": str(result[x][1].get(f"valueforfield{i}", None))[3:-2] for i in range(1, 7)}
    all_users.append(user)

Using both a list comprehension and a dict comprehension to do it all in one line:

all_users = [{
        f"field{i}": str(result[x][1].get(f"valueforfield{i}", None))[3:-2] 
        for i in range(1, 7)
    } for x in range(len(result))]

The difficulty in the example you provided comes in the names of the keys - but since those are regular, I used a format string to just insert the integer that the key expects (that is, f"field{i}" resolves to "field1" when i = 1, "field2" when i = 2, and so on).


In general, comprehensions don't really optimize for speed - they're more for avoiding code reuse.

Upvotes: 1

Related Questions