I've been trying to turn the output of my list comprehension into a variable. Quite silly, but no matter what I try, I seem to end up with an empty list (or NoneType variable).
I'm guessing it has something to do with the generator that it uses, but I'm not sure how to get around it as I need the generator to retrieve the desired results from my JSON file. (And I'm too much of a list comprehension and generator newbie to see how).
This is the working piece of code (originally posted as an answer to these questions (here and here)).
I'd like the output of the print() part to be written to a list.
def item_generator(json_Response_GT, identifier):
if isinstance(json_Response_GT, dict):
for k, v in json_Response_GT.items():
if k == identifier:
yield v
else:
yield from item_generator(v, identifier)
elif isinstance(json_Response_GT, list):
for item in json_Response_GT:
yield from item_generator(item, identifier)
res = item_generator(json_Response_GT, "identifier")
print([x for x in res])
Any help would be greatly appreciated!
A generator keeps its state, so after you iterate through it once (in order to print), another iteration will start at the end and yield nothing.
print([x for x in res]) # res is used up here
a = [x for x in res] # nothing left in res
Instead, do this:
a = [x for x in res] # or a = list(res)
# now res is used up, but a is a fixed list - it can be read and accessed as many times as you want without changing its state
print(a)
res = [x for x in item_generator(json_Response_GT, "identifier")] should do the trick.
Related
I have a list containing:
NewL = [(1.1,[01,02]),(1.2,[03,04]),(1.3,[05,06])]
and i used enumerate to obtain the list as above where the square brackets containing [01,02],[03,04] and [05,06] are generally obtained from another list. I'll show it just in case:
L = [[01,02],[03,04],[05,06]]
and initially the output list is just:
OutputList = [1.1,1.2,1.3]
i used enumerate on both of this list to get what i have as the first list i've written above.
The problem i'm facing now is, let's say i want to only output the value for [05,06] which is 1.3 from the NewL. How would i do that? I was thinking of something like:
for val in NewL:
if NewL[1] == [05,06]:
print NewL[0]
but it's totally wrong as cases might change where it's not necessary always be [05,06] as it can be obtaining value for [03,04] and [01,02] too. I'm pretty new using enumerate so I'll appreciate any help for this.
The for loop should like this:
for val in NewL:
if val[1] == [5,6]:
print val[0]
It will print 1.3
I'm not sure I understand the question, so I will extrapolate what you need:
Given your 2 intial lists:
L = [[01,02],[03,04],[05,06]]
OutputList = [1.1,1.2,1.3]
you can generate your transformed list using:
NewL = list(zip(OutputList, L))
then, given 1 item from L, if you want to retrieve the value from OutputList:
val = [x for x, y in NewL if y == [05,06]][0]
But it would be a lot easier to just do:
val = OutputList[L.index([05,06])]
Note that both those expressions will raise an IndexError if the searched item is not found
I'm parsing JSON objects and found this sample line of code which I kind of understand but would appreciate a more detailed explanation of:
for record in [x for x in records.split("\n") if x.strip() != '']:
I know it is spliting records to get individual records by the new line character however I was wondering why it looks so complicated? is it a case that we can't have something like this:
for record in records.split("\n") if x.strip() != '']:
So what do the brackets do []? and why do we have x twice in x for x in records.split....
Thanks
The "brackets" in your example constructs a new list from an old one, this is called list comprehension.
The basic idea with [f(x) for x in xs if condition] is:
def list_comprehension(xs):
result = []
for x in xs:
if condition:
result.append(f(x))
return result
The f(x) can be any expression, containing x or not.
That's a list comprehension, a neat way of creating lists with certain conditions on the fly.
You can make it a short form of this:
a = []
for record in records.split("\n"):
if record.strip() != '':
a.append(record)
for record in a:
# do something
The square brackets ( [] ) usually signal a list in Python.
I am trying to get shared letters from a string compared to a list of letters. I only return the last letter of l that shares with w . I want all the shared letters instead.
def f(w,l):
common = []
for i in w:
if in i in l:
return common.append(i)
As soon as i is in l your code returns, which immediately exits your function. instead do this:
def f(w,l):
common = []
for i in w:
if i in l:
common.append(i) # no return needed so it will collect all
return common
Make sure you return common at the end your function so you get all the values stored in common.
try this:
def f(w,l):
common = []
for i in w:
if i in l:
common.append(i)
return common
The problem is that the .append method of a list returns None. You were returning from the function the first time you did .append, so you were always going to return None from the function.
I think that what you are really looking for is a list comprehension:
def f(w,l):
return [i for i in w if i in l]
As others have pointed out, you might want to choose more descriptive variable names.
My code is as follows:
self.newMonsterList =[]
myKeys = []
if (len(self.myList)>0):
for i in range(len(self.myList)-1):
myVar = self.myList[i]
myKeys.append(myVar[1])
lis = game.active_entities.keys()
for k in lis:
if (k not in myKeys):
game.active_entities[k].destroy()
for it in self.myList:
if (it[1] in lis):
self.setEnt(it, game.active_entities[it[1]])
else:
self.newMonsterList.append(it)
self.makeEnt()
This code, that is the method in which it is, is called in a while loop which apparently works.
makeEnt appends an Entity with it[1] as Key to self.newMonsterList.
This works, I have tested it. Therefore, an ID which is in newMonsterList after the first full round of all this code (i.e. of the while loop which calls this code) should not be there after the second.
It is, however.
If, on the other hand, I check in makeEnt whether or not the content of newMonsterList already is a key, I get correct results.
I therefore conclude that newMonsterList is not properly emptied in which run of the while-loop.
I have been trying different versions for 2 hors now....anyone got an idea?
I am trying to write that down simpler:
a is a list of Ints
d is a dict with ints as keys
While True:
b=[]
for it in a:
if (it not in d):
b.append(it)
print it
else:
print it
for k in b:
d[k] = k
I found out now that the monsterlist is indeed emptied at each turn, however, in the ifclause ("if (it not in d):"), "it" is appened to the list each turn. However, "it" is also definitely in d after the first iteration, I can print it.
You are aware that this loop iterates over self.myList, but skips the last item in the list, right?
myKeys = []
if (len(self.myList)>0):
for i in range(len(self.myList)-1):
myVar = self.myList[i]
myKeys.append(myVar[1])
lis = game.active_entities.keys()
That seems suspicious to skip the last item.
FYI, I think the above code is equivalent to:
assert self.myList # Because if self.myList was empty, iterating over
# lis (later) would have caused an NameError.
myKeys = [value for key, value in self.myList[:-1]]
lis = game.active_entries.keys()
I'm looking for a "nice" way to process a list where some elements need to be expanded into more elements (only once, no expansion on the results).
Standard iterative way would be to do:
i=0
while i < len(l):
if needs_expanding(l[i]):
new_is = expand(l[i])
l[i:i] = new_is
i += len(new_is)
else:
i += 1
which is pretty ugly. I could rewrite the contents into a new list with:
nl = []
for x in l:
if needs_expanding(x):
nl += expand(x)
else:
nl.append(x)
But they both seem too long. Or I could simply do 2 passes and flatten the list later:
flatten(expand(x) if needs_expanding(x) else x for x in l)
# or
def try_expanding(x)....
flatten(try_expanding(x) for x in l)
but this doesn't feel "right" either.
Are there any other clear ways of doing this?
Your last two answers are what I would do. I'm not familiar with flatten() though, but if you have such a function then that looks ideal. You can also use the built-in sum():
sum(expand(x) if needs_expanding(x) else [x] for x in l, [])
sum(needs_expanding(x) and expand(x) or [x] for x in l, [])
If you do not need random access in the list you are generating, you could also use write a generator.
def iter_new_list(old_list):
for x in old_list:
if needs_expanding(x):
for y in expand(x):
yield y
else:
yield x
new_list = list(iter_new_list(old_list))
This is functionally equivalent to your second example, but it might be more readable in your real-world situation.
Also, Python coding standards forbid the use of lowercase-L as a variable name, as it is nearly indistinguishable from the numeral one.
The last one is probably your most pythonic, but you could try an implied loop (or in py3, generator) with map:
flatten(map(lambda x: expand(x) if needs_expanding(x) else x, l))
flatten(map(try_expanding, l))