Make a list consistent - python

I have 2 list ..
a = [{'Work': 'R'}, {'Area': 'S0'}, {'Type': 'PIV'}, {'Disc': 'LA'}, {'L': 'A'}]
b = [{'Key': '9', 'FileName': '123A.pdf', 'Code': '1', 'Type': 'PNHRG'}]
output -- [{'Key': '9', 'FileName': '123A.pdf', 'Code': '1', 'Type': 'PNHRG','Work': 'R','Area': 'S0','Type': 'PIV','Disc': 'LA','L': 'A'}]
I tried 'extend','append','insert' but did not get desired
output. tried all most all list operations with loops too. I am
not in position to change any kind of types for this.
Tried this solution too without luck. not sure where I am missing.
How do I make a flat list out of a list of lists?

You can use a doubly-nested dictionary comprehension, iterating over all the items in all the dicts in all the lists. Assuming multiple dicts in b might not be necessary, but makes it easier.
>>> a = [{'Work': 'R'}, {'Area': 'S0'}, {'Type': 'PIV'}, {'Disc': 'LA'}, {'L': 'A'}]
>>> b = [{'Key': '9', 'FileName': '123A.pdf', 'Code': '1', 'Type': 'PNHRG'}]
>>> [{k: v for lst in (a, b) for d in lst for k, v in d.items()}]
[{'Work': 'R', 'Area': 'S0', 'Type': 'PNHRG', 'Disc': 'LA', 'L': 'A', 'Key': '9', 'FileName': '123A.pdf', 'Code': '1'}]
Addendum: If there are any keys that appear in more than one dictionary, as is the case with "type" here, the value from the last dictionary that was iterated in the comprehension will be used, i.e. b here. If you need the value from a, do ... for lst in (b, a).... In your expected output, that key appears twice, but that is not possible unless you change the format, as in the other answer.

Extra from the answer provided by tobias_k:
If you want to combine both lists of dictionaries (and more when you have it) as a dictionary with a list of values in the same key. You can do this.
from collections import defaultdict
mydict = defaultdict(list)
for i in (a+b):
for key, value in i.items():
mydict[key].append(value)
mydict
Out[32]:
defaultdict(list,
{'Work': ['R'],
'Area': ['S0'],
'Type': ['PIV', 'PNHRG'],
'Disc': ['LA'],
'L': ['A'],
'Key': ['9'],
'FileName': ['123A.pdf'],
'Code': ['1']})

Related

Convert values from list of dictionaries from string to integer

I have a list of 54 dictionaries, formatted as so:
[{'1A': '1',
'3E': '2',
'PRODUCT NUMBER': '1',
'Week': '1'}
,
{'1A': '1',
'1B': '1',
'1C': '1',
'1D': '2',
'1E': '2',
'2C': '1',
'3E': '2',
'PRODUCT NUMBER': '2',
'Week': '1'},...] and etc
I am trying to convert the values from strings to integers.
I have successfully managed to do this for my very last dictionary, but it doesnt seem to be working for the rest.
This is my code:
for i in buyers: #buyers is the list
for n in buyers_dict: # the code works without this line the same, i cant figure out where to implement the 'n'
for k, v in buyers_list.items():
buyers_list[k] = int(v)
pprint.pprint(buyers)
Like I said, the 54th dictionary values are converted, but the rest are still strings
here is my excel file:
I've then condensed the dictionaries to just contain the key values pairs that have a value. Now I need to convert the values into integers.
Assuming your data is in this schema:
buyers = [{...}, {...}, ...]
You need to loop through the list of dicts then work on those dicts in particular:
for d in buyers:
for k, v in d.items():
d[k] = int(v)
Or in comprehension form:
buyers = [{k: int(v) for k, v in d.items()} for d in buyers]
d=[{'1A': '1',
'3E': '2',
'PRODUCT NUMBER': '1',
'Week': '1'}]
Using Comprehension
[{k:int(v)} for i in d for (k,v) in i.items() ]
Output:
[{'1A': 1}, {'3E': 2}, {'PRODUCT NUMBER': 1}, {'Week': 1}]

How to get values from dictionary in python?

I want to add value of entity_id with attribute for type which is String.
Below are the details of code:
entities = [{'id': 'Room1',
'temperature': {'value': '10', 'type': 'String'},
'pressure': {'value': '12', 'type': 'Number'},
'type': 'Room',
'time_index': '2020-08-24T06:23:37.346348'},
{'id': 'Room2',
'temperature': {'value': '10', 'type': 'Number'},
'pressure': {'value': '12', 'type': 'Number'},
'type': 'Room',
'time_index': '2020-08-24T06:23:37.346664'},
{'id': 'Room3',
'temperature': {'value': '10', 'type': 'Number'},
'pressure': {'value': '12', 'type': 'Number'},
'type': 'Array',
'time_index': '2020-08-24T06:23:37.346664'}]
attr = ['temperature','pressure']
self.logger.warning(msg.format( attr, entity_id)
How can i add value of id where type is String with warning msg.format in above code..
New to python so any help on it will be great.Thanks
To get the value of a dictionary key you do the following.
dict = {'a':1, 'b':2}
print(dict['a'])
This will print the result 1
If you have a dictionary inside a dictionary then do the following
dict = {1: {'a': 'abc', 'b': 'xyz'}}
print(dict[1][a])
This will print abc
Another alternative to putting dictionaries inside dictionaries would be to make a particular key hold a tuple, look at the following example
dict = {'a': ('abc', 'xyz'), 'b':('qwe', 12)}
for i in dict:
print(dict[i][1])
This will iterate through your dictionary and print xyz and 12. You could also give a condition to print it only if it meets a particular age by following this.
You can also iterate through your nested dictionaries if you desire that.
Depending on your need you can make it hold a dictionary or a tuple however, I think a tuple makes it easier to read and understand code (this is my preference).

How to know if a value is inside a nested dictionary?

I'm new to Python and I'm still learning how to use. I have the follow dictionary:
dic = {'0': {'text': 'a', 'lang': 'es', 'rating': '4'}, '1': {'text': 'b', 'lang': 'es', 'rating': '3'}, '2': {'text': 'c', 'lang': 'es', 'rating': '1'}, '3': {'text': 'd', 'lang': 'es', 'rating': '2'}, '4': {'text': 'e', 'lang': 'es', 'rating': '5'}}
Now, I'm trying to know if the text, for example, 'a' is a value of any of those nested dictionaries (I know there is a value() function which returns the values of the dictionaries, but in this case it will only return the values of the first dictionary, won't it? Like 0,1,2,3,4)
I tried
for i in range(len(dic)):
if text in dic[i].values():
print("Yes")
else:
print("No")
But this gives me a KeyError with value '0'. I have searched for similar questions, but haven't found any which I can use to solve my problem. Can you please help me? Thanks in advance.
You can use any:
dic = {'0': {'text': 'a', 'lang': 'es', 'rating': '4'}, '1': {'text': 'b', 'lang': 'es', 'rating': '3'}, '2': {'text': 'c', 'lang': 'es', 'rating': '1'}, '3': {'text': 'd', 'lang': 'es', 'rating': '2'}, '4': {'text': 'e', 'lang': 'es', 'rating': '5'}}
result = any('a' in d.values() for d in dic.values())
You can use any with a generator comprehension, as suggested by #Ajax1234.
Or, if you do this repeatedly, you can calculate a set of values and check for membership with O(1) complexity. itertool.chain is a useful tool to combine nested values:
from itertools import chain
values = set(chain.from_iterable(i.values() for i in dic.values()))
res = 'a' in values # True
Starting first from what you have tried, you could indeed:
Use a for loop to iterate over the values of dic, that are dictionaries too.
Check inside each dictionary if the value of the key 'text' equals 'a'.
If yes, then print 'Yes' and stop the loop.
If the loop ends without any match, then print 'No'.
Let's do it with a beautiful for/else statement:
for d in dic.values():
if d['text'] == 'a':
print("Yes")
break
else:
print("No")
To go further, you could also:
use comprehension to perform the for loop and the == operation in a smarter Python way,
and use any to replace the if and break statements by a smarter Python built-in function.
This shorter code will in fact do exactly the same things as previous one, in a really pythonic way:
if any(d['text'] == 'a' for d in dic.values()):
print("Yes")
else:
print("No")
Enjoy !
if you are sure that the string you are looking for will no be in key names, then another simple solution is converting whole dict to str and searching for string
if 'a' in str(dic):
print("a is there")
You are treating the dictionary as a list. You cannot index into a dictionary, like this:
dic[0]
But you can get the value from a given key, like so:
dic["0"] # yields {'text': 'a', 'lang': 'es', 'rating': '4'}
As such, modify your for loop as follows:
for i in dic:
...

Merging dictionaries of dictionaries

I'd like to know what be the best/most pythonic way to combine two dictionaries of dictionaries.
I have two dictionaries that look like so:
original = {'user1': {'COL': 'green', 'ID': '234235', 'NAME': 'andy'},
'user2': {'COL': 'blue', 'ID': '234234', 'NAME': 'john'}}
update = {'user1': {'COL': 'black', 'ID': '234235', 'NAME': 'andy'},
'user2': {'COL': 'purple', 'SPEC': 'na'}}
I would like to merge them together so that values found in the update dictionary would update the respective values in the original dictionary.
result = {'user1': {'COL': 'black', 'ID': '234235', 'NAME': 'andy'},
'user2': {'COL': 'purple', 'ID': '234234', 'NAME': 'john', 'SPEC': 'na'}}
I have tried using collections and copy, however, I end up replacing the entire value for the key.
That is just a simple for-loop:
for k in original:
original[k].update(update.get(k, {}))
for k in update:
if k in original:
original[k].update(update[k])
else:
original[k] = update[k]
This is assuming only one level of nesting. A deeper solution promises to be more complex. This also mutates the dictionary original, which may not be the behavior you want.
You could use double iteration if there are two levels each time:
for user, values in update.iteritems():
for k, v in values.iteritems():
original[user][k] = v
You may create a nested dict comprehension expression to achieve it:
{k1: {k2: update[k1].get(k2, v2) for k2, v2 in v1.items()} for k1, v1 in original.items()}
which will return value:
{'user2': {'ID': '234234', 'NAME': 'john', 'COL': 'purple'}, 'user1': {'ID': '234235', 'NAME': 'andy', 'COL': 'black'}}

How should I remove all dicts from a list that have None as one of their values?

Suppose I have a list like so:
[{'name': 'Blah1', 'age': x}, {'name': 'Blah2', 'age': y}, {'name': None, 'age': None}]
It is guaranteed that both 'name' and 'age' values will either be filled or empty.
I tried this:
for person_dict in list:
if person_dict['name'] == None:
list.remove(person_dict)
But obviously that does not work because the for loop skips over an index sometimes and ignores some blank people.
I am relatively new to Python, and I am wondering if there is a list method that can target dicts with a certain value associated with a key.
EDIT: Fixed tuple notation to list as comments pointed out
Just test for the presence of None in the dict's values to test ALL dict keys for the None value:
>>> ToD=({'name': 'Blah1', 'age': 'x'}, {'name': 'Blah2', 'age': 'y'}, {'name': None, 'age': None})
>>> [e for e in ToD if None not in e.values()]
[{'age': 'x', 'name': 'Blah1'}, {'age': 'y', 'name': 'Blah2'}]
Or, use filter:
>>> filter(lambda d: None not in d.values(), ToD)
({'age': 'x', 'name': 'Blah1'}, {'age': 'y', 'name': 'Blah2'})
Or, if it is a limited test to 'name':
>>> filter(lambda d: d['name'], ToD)
({'age': 'x', 'name': 'Blah1'}, {'age': 'y', 'name': 'Blah2'})
You can use list comprehension as a filter like this
[c_dict for c_dict in dict_lst if all(c_dict[key] is not None for key in c_dict)]
This will make sure that you get only the dictionaries where all the values are not None.
for index,person_dict in enumerate(lis):
if person_dict['name'] == None:
del lis[index]
you can also try
lis=[person_dict for person_dict in lis if person_dict['name'] != None]
never use List as variable
You can create new list with accepted data. If you have tuple then you have to create new list.
List comprehension could be faster but this version is more readable for beginners.
data = ({'name': 'Blah1', 'age': 'x'}, {'name': 'Blah2', 'age': 'y'}, {'name': None, 'age': None})
new_data = []
for x in data:
if x['name']: # if x['name'] is not None and x['name'] != ''
new_data.append(x)
print new_data

Categories

Resources