I have a string as below
gmr='rule:unique,attribute:geo,name:unq1,rule:sum,attribute:sales,name:sum_sales'
If you see clearly its kind of 2 dictionaries
rule:unique,attribute:geo,name:unq1
and
rule:sum,attribute:sales,name:sum_sales
I want to convert them to as below
[
{'rule': 'sum', 'attribute': 'sales', 'name': 'sum_sales'},
{'rule': 'unique', 'attribute': 'geo', 'name': 'uniq1'}
]
Kindly help
I tried
gmr='rule:unique,attribute:geo,name:unq1,rule:sum,attribute:sales,name:sum_sales'
dlist=[]
at_rule_gm=(x.split(':') for x in gmr.split(','))
dict(at_rule_gm)
but here I get only the last dictionary.
Start with sample of OP:
>>> gmr='rule:unique,attribute:geo,name:unq1,rule:sum,attribute:sales,name:sum_sales'
Make an empty list first.
>>> dlist = [ ]
Loop with entry over list, yielded by gmr.split(','),
Store entry.split(':') into pair,
Check whether first value in pair (the key) is 'rule'
If so, append a new empty dictionary to dlist
Store pair into last entry of dlist:
>>> for entry in gmr.split(','):
pair = entry.split(':')
if pair[0] == 'rule':
dlist.append({ })
dlist[-1][pair[0]] = pair[1]
Print result:
>>> print(dlist)
[{'name': 'unq1', 'attribute': 'geo', 'rule': 'unique'},
{'name': 'sum_sales', 'attribute': 'sales', 'rule': 'sum'}]
Looks like what OP intended to get.
gmr='rule:unique,attribute:geo,name:unq1,rule:sum,attribute:sales,name:sum_sales'
split_str = gmr.split(',')
dlist = []
for num in range(0, len(split_str),3):
temp_dict = {}
temp1 = split_str[num]
temp2 = split_str[num+1]
temp3 = split_str[num+2]
key,value = temp1.split(':')
temp_dict.update({key:value})
key,value = temp2.split(':')
temp_dict.update({key:value})
key,value = temp3.split(':')
temp_dict.update({key:value})
dlist.append(temp_dict)
dict always gives a single dictionary, not a list of dictionaries. For the latter, you can use a list comprehension after first splitting by 'rule:':
gmr = 'rule:unique,attribute:geo,name:unq1,rule:sum,attribute:sales,name:sum_sales'
items = (f'rule:{x}' for x in filter(None, gmr.split('rule:')))
res = [dict(x.split(':') for x in item.split(',') if x) for item in items]
print(res)
# [{'attribute': 'geo', 'name': 'unq1', 'rule': 'unique'},
# {'attribute': 'sales', 'name': 'sum_sales', 'rule': 'sum'}]
Related
I've one list of dictionary, i want to fetch the max floating point number from 'confidence' where keys ('key') are same.
ab = [{'key': 'gdpr.gdpr_compliance.1', 'value': 'Yes', 'idref': '69dbdba4-14d4-4ac8-a318-0d658e4d5b07', 'xpath': '/html/body/p[24]', 'confidence': 0.985},
{'key': 'gdpr.gdpr_compliance.2', 'value': 'Yes', 'idref': '69e2589a-bbf2-49c3-96fc-01fbee5dde03', 'xpath': '/html/body/p[27]', 'confidence': 0.989},
{'key': 'data_collected.personally_identifiable_information.1', 'value': 'Yes', 'idref': 'f6819b54-07a7-4839-b0cc-8343eed28342', 'xpath': '/html/body/ul[6]/li[1]', 'confidence': 0.562},
{'key': 'data_collected.personally_identifiable_information.2', 'value': 'Yes', 'idref': '496400e5-9665-4697-96bc-c55176cdbd02', 'xpath': '/html/body/ul[6]/li[2]', 'confidence': 0.661}]
Here you can observe 1st two dictionary having gdpr but 3rd dictionary having data_collected.
Here i don't understand how we can get the max value
i tried to do in this way
lis = []
for i in ab:
spl = i['key'].split('.')[0]
i['key'] = spl
if i['key'] == spl:
lis.append(i['confidence'])
print(lis)
expected output should be: [0.989, 0.661]
I'm not sure why you want to get a list when your data is key-based. I'd use a dict myself, but then again, maybe you only want to compare neighbouring values, which you can do with itertools.groupby. I'll include both methods below.
dict
maxes = {}
for d in ab:
confidence = d['confidence']
spl = d['key'].split('.')[0]
if spl not in maxes or confidence > maxes[spl]:
maxes[spl] = confidence
print(maxes)
{'gdpr': 0.989, 'data_collected': 0.661}
groupby
from itertools import groupby
grouper = groupby(ab, lambda d: d['key'].split('.')[0])
maxes = [(k, max(d['confidence'] for d in g)) for k, g in grouper]
print(maxes)
[('gdpr', 0.989), ('data_collected', 0.661)]
Here I'm keeping the keys, but you could very well discard them.
lis = [max(d['confidence'] for d in g) for _k, g in grouper]
print(lis)
[0.989, 0.661]
Where you went wrong
You split i['key'] then you assigned the same value back. It doesn't make sense.
Second you assigned i['key'] to spl then you immediately checked if they are equal. Obviously they will be.
A right approach
Dictionary
highest_value_dict = {}
for i in ab:
spl = i['key'].split('.')[0]
# if no such key, then add it.
# else check if this key is greater than the one in highest_value_dict
if spl not in highest_value_dict or highest_value_dict[spl] < i['confidence']:
highest_value_dict[spl] = i['confidence']
Output :
{'gdpr': 0.989, 'data_collected': 0.661}
If you really want the values as list
list(highest_value_dict.values())
Output :
[0.989, 0.661]
Something like the below. The idea is to use defaultdict that will map the key to the max confidence
from collections import defaultdict
ab = [{'key': 'gdpr.gdpr_compliance.1', 'value': 'Yes', 'idref': '69dbdba4-14d4-4ac8-a318-0d658e4d5b07',
'xpath': '/html/body/p[24]', 'confidence': 0.985},
{'key': 'gdpr.gdpr_compliance.2', 'value': 'Yes', 'idref': '69e2589a-bbf2-49c3-96fc-01fbee5dde03',
'xpath': '/html/body/p[27]', 'confidence': 0.989},
{'key': 'data_collected.personally_identifiable_information.1', 'value': 'Yes',
'idref': 'f6819b54-07a7-4839-b0cc-8343eed28342', 'xpath': '/html/body/ul[6]/li[1]', 'confidence': 0.562},
{'key': 'data_collected.personally_identifiable_information.2', 'value': 'Yes',
'idref': '496400e5-9665-4697-96bc-c55176cdbd02', 'xpath': '/html/body/ul[6]/li[2]', 'confidence': 0.661}]
data = defaultdict(float)
for entry in ab:
value = entry['confidence']
key = entry['key'].split('.')[0]
if data[key] < value :
data[key] = value
for k,v in data.items():
print(f'{k} -> {v}')
output
gdpr -> 0.989
data_collected -> 0.661
I suggest solution with O(n) time and memory complexity:
from typing import List
def get_maximal_values(data: dict) -> List[float]:
# Create iterator for extracting needed data
preparing_data = ((x['key'].split('.')[0], x['confidence']) for x in data)
# Find maximum for each unique key
result = {}
for key, confidence in preparing_data:
result[key] = max(result.get(key, 0), confidence)
# return only confidence values
return list(result.values())
I have a list of tuples
data = [(2015-10-08,2016-07-17,2015-09-09,2014-01-29),(Alex, Jerry, Tony, Tom), (5,6,7,8)]
And I have a list, this list contains column headings.
title = [Date , Name, Age]
With this list and list of tuples I want a dictionary.
This is the expected output
output = {1:{'Date': 2015-10-08,2016-07-17,2015-09-09,2014-01-29} ,{'Name' : Alex, Jerry, Tony, Tom}, {'Age' : 5,6,7,8}}
Try this:
dict(zip(title, data))
Or for making them sets:
dict(zip(title, map(set, data)))
Try :
output = {}
output["Date"] = set(data[0])
output["Name"] = set(data[1])
output["Age"] = set(data[2])
data = [('2015-10-08','2016-07-17,2015-09-09','2014-01-29'),('Alex', 'Jerry', 'Tony', 'Tom'), (5,6,7,8)]
title = ['Date', 'Name', 'Age']
your_dict = {key: value for key, value in zip(title, data)}
Here is one of the solutions:
data = [('2015-10-08','2016-07-17','2015-09-09','2014-01-29'),('Alex', 'Jerry', 'Tony', 'Tom'), ('5','6','7','8')]
title = ['Date', 'Name', 'Age']
output = {}
for i in range(len(title)):
output[i+1] = {title[i]: ",".join(data[index])}
print (output)
Output:
{1: {'Date': '2015-10-08,2016-07-17,2015-09-09,2014-01-29'}, 2: {'Name': '2015-10-08,2016-07-17,2015-09-09,2014-01-29'}, 3: {'Age': '2015-10-08,2016-07-17,2015-09-09,2014-01-29'}}
I am trying to create a new list from a list of dictionary items.
Below is an example of 1 dictionary item.
{'id': 'bitcoin',
'symbol': 'btc',
'name': 'Bitcoin',
'current_price': 11907.43,
'market_cap': 220817187069,
'market_cap_rank': 1}
I want the list to just be of the id item. So what I am trying to achieve is a list with items {'bitcoin', 'etc', 'etc}
You can use list comprehension:
my_list = [{'id': 'bitcoin', 'symbol': 'btc', ...}, ...]
[d['id'] for d in my_list]
Which translates to : for each dictionary in my_list, extract the 'id' key.
id_list = [d["id"] for d in dictlist ]
This should work for you
list = [ i['id'] for i in list_of_dict]
this should help
Simple and readable code that solves the purpose:
main_list = []
for item in main_dict:
main_list.append(item.get("id", None))
print(main_list)
I have an exhaustive list of different categories with me:
myList = [
{'name': 'Sasha', 'category': 'Dog'},
{'name': 'Meow', 'category': 'Cat'},
{'name': 'Bark', 'category': 'Dog'}
]
I want them to break and a create smaller list within this bigList. It would be similar to this:
bigList = [
[
{'category': 'Dog', 'name': 'Sasha'},
{'category': 'Dog', 'name': 'Bark'}
],
[
{'category': 'Cat', 'name': 'Meow'}
]
]
Here is the python logic for iterating the loop:
bigList = []
prev = ''
for s in myList:
newList = []
if s['category'] != prev:
for m in myList:
if m['category'] == s['category']:
newList.append(m)
bigList.append(newList)
prev = s['category']
This has done the trick for me but I would like to know how can I optimize the above logic in for loop for more shorter and efficient code.
You can do this in two steps with groupby as commented by #roganjosh:
from itertools import groupby
# step 1: sort the list by category, we need this step because groupby only groups same
# adjacent values so we need to sort the list so that same category are close to each other
sort_list = sorted(myList, key = lambda x: x["category"])
# step 2: group by the category and create a new sub list for each group
[list(g) for _, g in groupby(sort_list, key = lambda x: x['category'])]
#[[{'category': 'Cat', 'name': 'Meow'}],
# [{'category': 'Dog', 'name': 'Sasha'}, {'category': 'Dog', 'name': 'Bark'}]]
Sorting can be expensive for large lists.
Starting with your data:
my_list = [
{'name': 'Sasha', 'category': 'Dog'},
{'name': 'Meow', 'category': 'Cat'},
{'name': 'Bark', 'category': 'Dog'}
]
This loops through all elements of your list once and rembers what its has already seen before in a dictionary:
res = []
seen = {}
for entry in my_list:
val = seen.setdefault(entry['category'], [])
if not val:
res.append(val)
val.append(entry)
It appends a new list only for not yet seen entries to res but all entries to the corresponding nested list val that it got from the seen dictionary. So, the same val is in res and in seen. Hence, appending to val will enlarge val and the effect can be seen no matter if your access val through res and or seen. The line val = seen.setdefault(entry['category'], []) gives you either an existing list, if the category was seen before or, a new empty list if the category was encountered the first time. At the same time, if the category is not yet in seen, it adds a new key with an empty list as value to seen.
This is the result:
import pprint
pprint.pprint(res)
[[{'category': 'Dog', 'name': 'Sasha'}, {'category': 'Dog', 'name': 'Bark'}],
[{'category': 'Cat', 'name': 'Meow'}]]
I would like to split a string like this:
my_list = [{'lat': -27.239722222222223, 'name': 'Geraldton', 'long': 114.62222222222222}]
into individual values:
my_list2 = ['lat', -27.239,'name', 'Geraldton', 'long', 114.6222]
or into dictionary or list where I can call the elements to use.
You can use dict.items to get all tuples (key, value) in the dictionary, all that is left is to flatten them:
my_list = [{'lat': -27.239722222222223, 'name': 'Geraldton', 'long': 114.62222222222222}]
dictionary = my_list[0]
# flatten using list comprehension
flattened = [item for tup in dictionary.items() for item in tup]
Output:
['lat', -27.239722222222223, 'long', 114.62222222222222, 'name', 'Geraldton']
You could do something like this:
list1 = [{'lat': -27.239722222222223, 'name': 'Geraldton', 'long': 114.62222222222222}]
list2 = []
for key in list1[0]:
list2.append(key)
list2.append(list1[0][key])