Access prior element in a list comprehension - python

I've looked around into list comprehensions on here, and can find a solution for this.
Closest I've come is questions that advice using enumerate() while iterating in a list comprehension.
What I'd like to do is access the prior element in a list comprehension. The context is this question on another StackExchange site.
Basically, if I get this string from stdin - 4,6,+2,+8, I'd like to output the array that is the integer of the number, or the number plus the value of the prior element. In the given case the final array is: 4,6,8,16 - or 4,6,6+2,(6+2)+8. Going from left to right with an array and for loop its trivial to generate, but I'm curious to know if it can be done in a single list comprehension.
As for what I have:
from sys import*
s=argv[1].split(',')
for i in range(len(s)):
s[i]=eval(`s[i-1]`*(s[i][0]=='+')+s[i])
print s
Which prints the correct result, however the following list comprehension does not:
s=argv[1].split(',')
s=[eval(s[i-1]*(x[0]=='+')+x) for i,x in enumerate(s)]
print s
Which results in:
[4, 6, 8, 10]
Which is equivilient to 4, 6, +2+6, +2+8.
What I'd like to be able to do finally is something along the lines of:
s=[eval(PRIOR_VALUE*(x[0]=='+')+x) for x in argv[1].split(',')]
So can I easily access the prior computed element of a list comprehension in the same list comprehension?

So can I easily access the prior computed element of a list comprehension in the same list comprehension?
Easily? No.
If you want to make things difficult for yourself, there are plenty of ways to save state information in a list comprehension. For example,
prev = [None]
s = [prev.__setitem__(0, val) or val
for item in list
for val in [something(item, prev[0])]]
This is not a good idea.

Related

Refer to a list in Python from within the [ ] operator

While trying to optimize a one-liner that extracts values from a list of dicts (all strings that come after keyword/ til the next /) I got stuck in the following:
imagine this list of dicts:
my_list = [{'name':'val_1', 'url':'foo/bar/keyword/bla_1/etc'}.......{'name':'val_z', 'url':'foo/bar/keyword/bla_n/etc'}]
The numbers in val_ and bla_ are not related.
I am trying to extract all the bla_x (they could be anything, no pattern possible) words using list comprehension for 0 < x < n+1. I managed to get the index of those elements in the split string
[d['url'].split('/').index('keyword') + 1 for d in my_list]
But what I need is to access that value and not only its index, so I thought about something like this:
[d['url'].split('/')[the_resulting_split_list.index('keyword') + 1] for d in my_list]
As far as my knowledge go, that seems impossible to do. Is there an alternative way to reach my goal of getting an output of ['bla_1', 'bla_2', ....., 'bla_n'] without having to run the split('/') operation twice in the list comprehension?
Let's not care about exceptions for now and assume input data is always correct.

How to add up values of the "sublists" within a list of lists

I have a list of lists in my script:
list = [[1,2]
[4,3]
[6,2]
[1,6]
[9,2]
[6,5]]
I am looking for a solution to sum up the contents of each "sublist" within the list of lists. The desired output would be:
new_list = [3,7,8,7,11,11]
I know about combining ALL of these lists into one which would be:
new_list = [27,20]
But that's not what i'm looking to accomplish.
I need to combine the two values within these "sublists" and have them remain as their own entry in the main list.
I would also greatly appreciate it if it was also explained how you solved the problem rather than just handing me the solution. I'm trying to learn python so even a minor explanation would be greatly appreciated.
Using Python 3.7.4
Thanks, Riftie.
The "manual" solution will be using a for loop.
new_list = []
for sub_list in list:
new_list.append(sum(sub_list))
or as list compherension:
new_list = [sum(sub_list) for sub_list in list]
The for loop iterates through the elements of list. In your case, list is a list of lists. So every element is a list byitself. That means that while iterating, sub_list is a simple list. To get a sum of list I used sum() build-in function. You can of course iterate manually and sum every element:
new_list = []
for sub_list in list:
sum_val = 0
for element in sub_list:
sum_val = sum_val + element
new_list.append(sum_val)
but no need for that.
A better approach will be to use numpy, which allows you to sum by axis, as it looks on list of lists like an array. Since you are learning basic python, it's too soon to learn about numpy. Just keep in mind that there is a package for handling multi-dimensions arrays and it allows it perform some actions like sum on an axis by your choice.
Edit: I've seen the other solution suggest. As both will work, I believe this solution is more "accessible" for someone who learn to program for first time. Using list comprehension is great and correct, but may be a bit confusing while first learning. Also as suggested, calling your variables list is a bad idea because it's keyword. Better names will be "my_list", "tmp_list" or something else.
Use list comprehension. Also avoid using keywords as variable names, in your case you overrode the builtin list.
# a, b -> sequence unpacking
summed = [a + b for a, b in lst] # where lst is your list of lists
# if the inner lists contain variable number of elements, a more
# concise solution would be
summed2 = [sum(seq) for seq in lst]
Read more about the powerful list comprehension here.

Initialize a list using inline for loop

I am initializing my list object using following code.
list = [
func1(centroids[0],value),
func1(centroids[1],value),
....,
func1(centroids[n],value)]
I am trying to do it a more elegant way using some inline iteration. Following is the pseudo code of one possible way.
list = [value for value in func1(centroids[n],value)]
I am not clear how to call func1 in an iterative way. Can you suggest a possible implementation?
For a list of objects, Python knows how to iterate over it directly so you can eliminate the index shown in most of the other answers,
res = [func1(c, value) for c in centroids]
That's all there is to it.
A simple list comprehension consists of the "template" list element, followed by the iterator needed to step through the desired values.
my_list = [func1(centroids[0],value)
for n in range(n+1)]
Use this code:
list = [func1(centroids[x], value) for x in range(n)]
This is called a list comprehension. Put the values that you want the list to contain up front, then followed by the for loop. You can use the iterating variable of the for loop with the value. In this code, you set up n number(s) of variable(s) from the function call func1(centroids[x], value). If the variable n equals to, let's say, 4, list = [func1(centroids[0], value), func1(centroids[0], value), func1(centroids[0], value), func1(centroids[0], value)] would be equal to the code above

Inquiry on dictionary comprehension

The following code is a bit from a bigger piece. lines is a 2D list and keyss is a 1D list. All element in lines is the same length as keyss.
datadict = []
for element in lines:
for index in range(len(element)):
datadict.append({keyss[index]: element[index]})
I was wondering if there was a way of writing this using dictionary comprehension? This is more of a curious question as the shown code works just fine for what I'm doing. I've been trying and couldn't find a way too. If you can could go over the syntax of how it would look a bit as well, Thanks!
EDIT#1:
Reading through the responses, I realized it wasn't really working. I'm trying to do a list comprehension where every element is a dictionary comprehension. I'm not entirely sure if that is possible or not. I want to make a list of dictionaries where I take every element in keyss and match index for index in a element in lines which is a list, if that makes sense.
EDIT #2:
I found data_list = [{keyss[i]:row[i] for i in range(len(keyss))} for row in lines] to work.
A dictionary comprehension creates a dictionary. You want a list comprehension:
datalist = [{keyss[index]:element[index]}) for element in lines
for index in range(len(element))]
You can find the documentation on the syntax here.
Your current code doesn't create a dictionary, but if that was your intent, this can be accomplished by
dict(zip(keyss, elements))
or the dictionary comprehension
{key: value for key, value in zip(keyss, elements)}
As mentioned by eugene, it will be list comprehension and not dict comprehension. You may further simplify the code by using zip() as you need the from element and keyss list corresponding to same index. Hence, your simplified list comprehension expression should be as:
datalist = [{k: e} for elements in lines for e, k in zip(elements, keyss)]

List comprehension

I have some trouble with list comprehension, I think I already know how to use it well but certainly I don't.
So here is my code:
vector1=[x for x in range(0,351,10)]
first=list(range(0,91))
second=list(range(100,181))
third=list(range(190,271))
fourth=list(range(280,351))
Quadrants=first+second+third+fourth
string=['First']*91+['Second']*81+['Third']*81+['Fourth']*71
vector2=dict(zip(Quadrants,string))
Quadrant=[]
for n in range (len(vector1)):
Quadrant+=[vector2[vector1[n])]]
So i want to do the for_loop with list comprehension, but i can't... I tried this:
Quadrant=[y3 for y3 in [vector2[vector1[i]]] for i in range (len(vector1))]
Here's the code you're trying to convert to a listcomp:
Quadrant=[]
for n in range (len(vector1)):
Quadrant+=[y[vector1[n]]]
First, you have to convert that into a form using append. There's really no reason to build a 1-element list out of y[vector1[n]] in the first place, so just scrap that and we have something we can appenddirectly:
Quadrant=[]
for n in range(len(vector1)):
Quadrant.append(y[vector1[n]])
And now, we have something we can convert directly into a list comprehension:
Quadrant = [y[vector1[n]] for n in range(len(vector1))]
That's all there is to it.
However, I'm not sure why you're doing for n in range(len(vector1)) in the first place if the only thing you need n for is vector1[n]. Just loop over vector1 directly:
Quadrant=[]
for value in vector1:
Quadrant.append(y[value])
Which, again, can be converted directly:
Quadrant = [y[value] for value in vector1]
However, all of this assumes that your original explicit loop is correct in the first place, which obviously it isn't. Your vector1 is a dict, not a list. Looping over it the keys from 0 to len(vector1) is just going to raise KeyErrors all over the place. Changing it to loop directly over vector1 is going to solve that problem, but it means you're looping over the keys. So… I have no idea what your code was actually trying to do, but get the simple but verbose version right first, and you can probably convert it to a comprehension just as easily as the above.

Categories

Resources