简体   繁体   中英

From the list of dictionaries find the largest value lengths for each key

data = [{"id": "78ab45",
         "name": "Jonh"},
        {"id": "69cd234457",
         "name": "Joe"}]

I want my function to return the largest value lengths for each key from all dictionaries:

expected_output = [
    { "size": 10, "name": "id" }, #because the length of the largest "id" value is 10
    { "size": 4, "name": "name" }, #because the length of the largest "name" value is 4
]

My code so far:

def my_func(data):
  headers_and_sizes = []
  for item in data:
     for key, value in item.items():
        headers_and_sizes.append({"size": f'{len(value)}', "name": key})
        if int(headers_and_sizes[0]["size"]) < len(value):
            headers_and_sizes[0]["size"] = len(value)
            
  return headers_and_sizes

Gives me this:

[{'size': '6', 'name': 'id'}, {'size': '4', 'name': 'name'}, {'size': '10', 'name': 'id'}, {'size': '3', 'name': 'name'}]

How can I fix that so that it will return the values as in expected_output ?

You'll want to be updating a dictionary that stores each key mapped to the maximum length seen for that key thus far.

data = [
  {
     "id": "78ab45",
     "name": "Jonh",
  },
  {
     "id": "69cd234457",
     "name": "Joe",
  },
]
key_to_max_len = {}
for datum in data:
   for key, val in datum.items():
        if key not in key_to_max_len or len(val) > key_to_max_len[key]:
            key_to_max_len[key] = len(val)
key_size_arr = [{"size": val, "name": key} for key, val in key_to_max_len.items()]

you can get the max value for id and name like below code, and structure the output accordingly

>>> data 
[{'id': '78ab45', 'name': 'Jonh'}, {'id': '69cd234457', 'name': 'Joe'}]
id  = max(map(lambda x:len(x['id']), data))
name  = max(map(lambda x:len(x['name']), data))
>>> id
10
>>> name
4

You can use list comprehension to form a tuple with ids and names:

names_ids = [(eachdict['id'],eachdict['name']) for eachdict in data]

Format the output to have the desired shape (dictionaries), find the max length (using the max() function, passing it the lengths of name s and id s, using another list comprehension, inside max() ):

expected_output = \
[{"size":max([len(each[0]) for each in names_ids]),"name":"id"},
 {"size":max([len(each[1]) for each in names_ids]),"name":"name"}] 

Output will be:

[{'name': 'id', 'size': 10}, {'name': 'name', 'size': 4}]

Using the following:

keys = list(data[0].keys())
output = {key:-1 for key in keys}
for d in data:
    for k in d.keys():
        if len(d[k]) > output[k]:
            output[k] = len(d[k])

Will output:

{'id': 10, 'name': 4}

I think the easiest method here is pandas...

import pandas as pd
df = pd.DataFrame(data)

out = [{'size': df['id'].str.len().max(), 'name':'id'},
       {'size': df['name'].str.len().max(), 'name':'name'}]

output:

[{'size': 10, 'name': 'id'}, {'size': 4, 'name': 'name'}]

or for addt'l names..

[{'size':df[col].str.len().max(), 'name':col} for col in df.columns]

Here is how you can use a nested dictionary comprehension:

data = [{"id": "78ab45",
         "name": "Jonh"},
        {"id": "69cd234457",
         "name": "Joe"}]


expected_output = [{'size': len(max([i[k] for i in data], key=len)),
                    'name': k} for k in data[0]]

print(expected_output)

Output:

[{'size': 10, 'name': 'id'},
 {'size': 4, 'name': 'name'}]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM