How can I simplify the following:
imgs = []
for i, obj in enumerate(objlist):
imgs.append( foo(obj, f"img-{i}.png") )
where objlist an array of objects
and foo is a method that processes the object and saves an image receiving both the object and the new file name, it returns the same name given.
This is a simple transformation into a list comprehension:
imgs = [foo(obj, f"img-{i}.png") for (i, obj) in enumerate(objlist)]
(btw you forgot the in in your for loop.
Also, see this answer on the general problem of converting nested for loops into a single list comprehension.
Related
I am having an issue to where I am attempting to yield a dictionary back to the caller and casting the returned generator to a list, however when i print event_list, it still states that it is a generator object.
My goal is to multi-process a function by a list of files that will create a local dictionary and return said dictionary to the caller so that I can make a single list containing the returned dictionaries from that method. Not entirely sure where I am going wrong.
import multiprocessing as mp
import json
class Events(object):
def __init__(self):
self._parse_events()
def _parse_events(self):
my_list = ['file1', 'file2', 'file3']
event_results = list()
with mp.Pool() as pool:
results = list(pool.map(self._get_event, my_list))
for result in results:
event_results.append(result)
print(event_results) # <------- this somehow returns a generator although I thought i casted the return to a list
print(sum(event_results, [])) # <--------- this doesn't work now that im dealing with a generator rather than the original list
def _get_event(self, filename):
key_identifier = 'role'
with open(filename, 'r') as data:
for line in data:
if key_identifier in line:
temp_dict = dict()
try:
contents = json.loads(line)
temp_dict['UTC'] = contents.get('utc', 'None')
temp_dict['ServiceID'] = contents[key_identifier].get('ServiceID', 'None')
except (KeyError, ValueError):
continue
if temp_dict: yield temp_dict
Your code is creating a list of generators. It's not the top level object that's not of the right type, it's the inner values, and you're not casting those at all. It may be that you intended to, as you currently have a mostly pointless extra loop where you move the generator objects from results into event_results without doing anything else to them.
You could change that loop to put the inner values into the list:
for result in results:
event_results.extend(result) # extend consumes an iterable
Or if you want a list of lists, rather than just one single flat list, you could do:
for result in results:
event_results.append(list(result)) # convert each generator into a list
I have created a function which returns a list
def GetAddressContainer(obj,obj1):
mylist = list()
for i in test['adresss']:
addresscotainer = i[id]
return mylist(addresscontainer)
When i call the function -
UkContainer = GetAddressContainer(Postcode,Country)
i get the following error message:
TypeError: 'list' object is not callable in python
Any ideas why i am getting this error and what i would have to update?
The problems seem to be in
return mylist(addresscontainer)
You using parentheses on the list and therefore calling it as a function, that's why you get the error. Without any more code I not entirely sure what to replace it with though.
Issues
The line mylist = list() basically creates an empty list which you can use to store any values. In the code mylist is being called (using (...)) which does not make sense in python since mylist is not a function.
Another issue with the code is that the value of addresscontainer is never being inserted into mylist.
Possible Solutions
So, as per your problem, either of the following solutions can be used:
Append addresscontainer into mylist iteratively within the for loop:
for i in test['adress']:
addresscontainer = i[id]
mylist.append(addresscontainer) # Inserts the value at the end of list
return mylist # Returns the list
[RECOMMENDED] Use list comprehension:
def GetAddressContainer(...):
return [i[id] for i in test['adress']] # Build list using "List Comprehension"
Replace mylist(addresscontainer) with list(addresscontainer) code.
Only list word could be a callable function because it defines a class of any list. And mylist = list() will be an instance of an abstract list, then, not callable.
change mylist = list() to mylist = []
it will create an empty list instead of a list object.
and you are not appending anything to the list.
I have some data like:
['6005,280', '6005,2751', '6005,260']
and I want to convert them into a list like:
[['6005','280'],['6005','2751'],['6005','260']]
I use
for i in range(len(mainText)):
target_list.append(int(x) for x in mainText[i].split(','))
But got some crazy output like:
[<generator object main.<locals>.<genexpr> at 0x000000DA61784C78>, <generator object main.<locals>.<genexpr> at 0x000000DA61784B10>, <generator object main.<locals>.<genexpr> at 0x000000DA61784CF0>]
So what is the correct way to do that?
Code:
import csv
def main():
inputfile=open('price.csv','r')
mainText=mainPart(inputfile)
## print(mainText)
target_list=[]
for i in range(len(mainText)):
target_list.append(int(x) for x in mainText[i].split(','))
print(target_list)
def mainPart(file):
## import items with first row
rowsWithEnter1=[row for row in file]
## del first row
rowsWithEnter2=rowsWithEnter1[1:]
rows=[]
for i in range(len(rowsWithEnter2)):
rows.append(rowsWithEnter2[i].strip('\n'))
return rows
main()
When you have a comprehension (like int(x) for x in ...) inside parentheses, it is interpreted as a generator, which is a special type of object which can then be iterated over to produce a list. The crazy output you're seeing is because you've actually created a list of generators, instead of a list of lists. To interpret your comprehensions as lists instead of generators, you just need to put them in square brackets:
for i in range(len(mainText)):
target_list.append([int(x) for x in mainText[i].split(',')])
A simple way to achieve what I think you want is the following:
mainText = ['6005,280', '6005,2751', '6005,260']
target_list = [elem.split(',') for elem in mainText]
A list comprehension should work:
[x.split(',') for x in mainText]
A less preferable alternative to #francisco's answer:
list(map(str.split, mainText))
Here's one way using list comprehension
l = ['6005,280', '6005,2751', '6005,260']
[list(item.split(',')) for item in l]
I have a list of dictionaries called lod. All dictionaries have the same keys but different values. I am trying to update one specific value in the list of values for the same key in all the dictionaries.
I am attempting to do it with the following for loop:
for i in range(len(lod)):
a=lod[i][key][:]
a[p]=a[p]+lov[i]
lod[i][key]=a
What's happening is each is each dictionary is getting updated len(lod) times so lod[0][key][p] is supposed to have lov[0] added to it but instead it is getting lov[0]+lov[1]+.... added to it.
What am I doing wrong?
Here is how I declared the list of dicts:
lod = [{} for _ in range(len(dataul))]
for j in range(len(dataul)):
for i in datakl:
rrdict[str.split(i,',')[0]]=list(str.split(i,',')[1:len(str.split(i,','))])
lod[j]=rrdict
The problem is in how you created the list of dictionaries. You probably did something like this:
list_of_dicts = [{}] * 20
That's actually the same dict 20 times. Try doing something like this:
list_of_dicts = [{} for _ in range(20)]
Without seeing how you actually created it, this is only an example solution to an example problem.
To know for sure, print this:
[id(x) for x in list_of_dicts]
If you defined it in the * 20 method, the id is the same for each dict. In the list comprehension method, the id is unique.
This it where the trouble starts: lod[j] = rrdict. lod itself is created properly with different dictionaries. Unfortunately, afterwards any references to the original dictionaries in the list get overwritten with a reference to rrdict. So in the end, the list contains only references to one single dictionary. Here is some more pythonic and readable way to solve your problem:
lod = [{} for _ in range(len(dataul))]
for rrdict in lod:
for line in datakl:
splt = line.split(',')
rrdict[splt[0]] = splt[1:]
You created the list of dictionaries correctly, as per other answer.
However, when you are updating individual dictionaries, you completely overwrite the list.
Removing noise from your code snippet:
lod = [{} for _ in range(whatever)]
for j in range(whatever):
# rrdict = lod[j] # Uncomment this as a possible fix.
for i in range(whatever):
rrdict[somekey] = somevalue
lod[j] = rrdict
Assignment on the last line throws away the empty dict that was in lod[j] and inserts a reference to the object represented by rrdict.
Not sure what your code does, but see a commented-out line - it might be the fix you are looking for.
I'm trying to remove duplicate items in a list through a dictionary:
def RemoveDuplicates(list):
d = dict()
for i in xrange(0, len(list)):
dict[list[i]] = 1 <------- error here
return d.keys()
But it is raising me the following error:
TypeError: 'type' object does not support item assignment
What is the problem?
You should have written:
d[list[i]] = 1
But why not do this?
def RemoveDuplicates(l):
return list(set(l))
Also, don't use built-in function names as variable names. It can lead to confusing bugs.
In addition to what others have said, it is unpythonic to do this:
for i in xrange(0, len(lst)):
do stuff with lst[i]
when you can do this instead:
for item in lst:
do stuff with item
dict is the type, you mean d[list[i]] = 1.
Addition: This points out the actual error in your code. But the answers provided by others provide better way to achieve what you are aiming at.
def remove_duplicates(myList):
return list (set(myList))
From looking at your code it seems that you are not bothered about the ordering of elements and concerned only about the uniqueness. In such a case, a set() could be a better data structure.
The problem in your code is just to use a function argument name which is not the name of the built-in type list and later on the type dict in the expression dict[list[i]].
Note that using list(set(seq)) will likely change the ordering of the remaining items. If retaining their order is important, you need to make a copy of the list:
items = set()
copy = []
for item in seq:
if not item in items:
copy.add(item)
items.append(item)
seq = copy