Trimming lists using a loop - python

I have few lists like:
a = [1, 2, 3, 4, 5]
b = [4, 6, 5, 9, 2]
c = [4, 7, 9, 1, 2]
I want to trim all of them using a loop, instead of doing as below:
a[-2:]
b[-2:]
c[-2:]
I tried but got confused with pass by value or pass by reference fundamentals, looked into other questions as well but no help.
Thanks

for l in [a, b, c]:
del l[-2:]
This removes the last two elements from each list. If you want to remove all but the last two elements only, do this:
for l in [a, b, c]:
del l[:-2]
There's no need to worry about references here; the list over which the for loop iterates contains references to a, b and c, and each list is mutated in-place by deleting a list slice.

x = [a, b, c]
x = map(lambda lst: lst[-2:], x)

Deleting the unwanted items from the existing lists, using a loop:
for list in [a, b, c]:
del a[:-2]
Or, creating new lists containing only the correct items, using a list comprehension:
(a, b, c) = [x[-2:] for x in (a, b, c)]

Related

Python splitting multiple lists

How can I split a list with multiple lists within in and store them in some sort of variable so they can be tested.
For example
[[2,3], [6,1,7,2], [3,4,1]]
Upon splitting will be something like this
[2,3]
[6,1,7,2]
[3,5,1,]
Where I can use each one of them as parameters for my other functions.
Is this possible, if so how can I produce this?
Thanks in advance, new to python sorry!
for x in [[2,3], [6,1,7,2], [3,4,1]]:
your_f(*x)
This will loop through the list of lists, selecting each sublist as x, and then unpacking the contents as parameters in your_f via the * (which has a special name somewhere).
Aka on the first iteration, the code will execute your_f(2, 3)
If you just want to extract inner lists to other variables you can use this:
li = [[2,3], [6,1,7,2], [3,4,1]]
a, b, c = li
print(a, b, c)
output is [2, 3] [6, 1, 7, 2] [3, 4, 1]
If you have a function that takes three lists you can use this:
def foo(a, b, c):
print(a, b, c)
foo(*li)
output is the same.
It is called Unpacking Argument Lists.

Extended sequence unpacking in python3

I create a list as:
>>> seq = [1, 2, 3, 4]
Now i assign the variables as follows:
>>> a, b, c, d, *e = seq
>>> print(a, b, c, d, e)
I get output as:
>>> 1 2 3 4 []
Now i change the sequence in which i assign variables as:
>>> a, b, *e, c, d = seq
>>> print(a, b, c, d, e)
I get output as:
>>> 1, 2, 3, 4, []
So my question is Why *e variable above is always assigned an empty list regardless of where it appears?
It was a design choice, according to PEP 3132 (with my bold):
A tuple (or list) on the left side of a simple assignment (unpacking is not defined for augmented assignment) may contain at most one expression prepended with a single asterisk (which is henceforth called a "starred" expression, while the other expressions in the list are called "mandatory"). This designates a subexpression that will be assigned a list of all items from the iterable being unpacked that are not assigned to any of the mandatory expressions, or an empty list if there are no such items.
Indeed, the first example in the PEP illustrates your point:
>>> a, *b, c = range(5)
>>> a
0
>>> c
4
>>> b
[1, 2, 3]
In the first case
a, b, c, d, *e = seq
since the sequence has only four elements, a, b, c and d get all of them and the rest of them will be stored in e. As nothing is left in the sequence, e is an empty list.
In the second case,
a, b, *e, c, d = seq
First two elements will be assigned to a and b respectively. But then we have two elements after the *e. So, the last two elements will be assigned to them. Now, there is nothing left in the seq. That is why it again gets an empty list.
a, b, *e, c, d = [1, 2, 3, 4]
*e says "what's left put into e". Because you have 4 elements, empty sequence is put into e.

needed help on list() and sort() funcion

I am a complete newbie to Python and am completely stuck. Basically, I have information in a list like the one below:
[a, b, c, d]
[e, f, g, h, i]
and so on....
From each list I want to get the second and the final data, so that it will return the following
b,d
f,i
I have been looking at using the sort() function or the split() function but to be honest I have no idea where to start.
Please can someone help me or point me in the right direction?
for lis in lists:
print(lis[1], lis[-1])
Where [1] gives the second element and [-1] gives the last. List indices start at 0, which is why [1] gives the second element. Negative indices are valid as well, and starting from -1, they count backwards from the end of the list. Negative indices are especially useful when dealing with lists of variable lengths.
In your case lists would be [[a, b, c, d], [e, f, g, h, i]].
You should do this:
# Assuming the letters below actually have values,
# otherwise you must make these characters
mylist = [a,b,c,d]
secondElement = mylist[1]
lastElement = mylist[-1]
list[-1] will return the last element of the list, and list[1] will return the second element of the list
something like
>>>a = [1,2,3,4]
>>>b = [5,6,7,8]
>>>print a[1],a[-1]
4,2
>>>print b[1],b[-1]
6,8
index from left: 0, 1, 2, 3
list : [5, 2, 2, 4]
index fro right: -4,-3,-2,-1

Python slice command forgotten out of the loop

I want to build some lists (a, b, c, d) by extending periodically those given in input.
The structure of the periodicity is such that the first element of each list must not be repeated, while all the other elements must be until the maximum length set in input is reached (it is possible that the period does not get to be repeated an integer number of times).
To give an example, if I have as input
a = [1, 2, 3, 4] max_len=11
I want to obtain as output
a = [1, 2, 3, 4, 2, 3, 4, 2, 3, 4, 2]
I wrote this piece of code:
for mylist in [a, b, c d]:
period = mylist[1:] # all elements but the first are repeated
while len(mylist)< max_len:
mylist.extend(period)
mylist = mylist[:max_len] # cut to max_len
print mylist
print a, b, c, d
If I run this, I see from the two print commands that my lists are how I want them to be while the program is still in the loop, but they get back to the "non-sliced" length when out of the loop, that is, a gets back to the length greater than max_len where the period is repeated exactly 4 times:
a = [1, 2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4]
Why is that? It looks like the program has forgotten the slicing (but not the extension).
I understand that it is a pretty simple problem, and I could get around it in some other way, but I would like to understand why this idea does not work.
Thank you for your help!
The problem is that mylist = mylist[:max_len] creates a new list instead of modifying mylist in place, so the results never propagate back to a et al.
If you replace:
mylist = mylist[:max_len]
with
mylist[:] = mylist[:max_len]
that'll fix it.
As an aside, you could use itertools for the transformation:
In [10]: [a[0]] + [v for v in itertools.islice(itertools.cycle(a[1:]), max_len - 1)]
Out[10]: [1, 2, 3, 4, 2, 3, 4, 2, 3, 4, 2]
mylist in the loop starts off referring to one of the input lists such as a but when you assign to it you are just rebinding the name mylist to a new list, you are not modifying the original list.
This would work:
for mylist in [a, b, c, d]:
period = mylist[1:] # all elements but the first are repeated
while len(mylist)< max_len:
mylist.extend(period)
mylist[:] = mylist[:max_len] # cut to max_len
print mylist
print a, b, c, d
The slice assignment updates the original list.
Or you could try this, just updating the original list once:
for mylist in [a, b, c, d]:
mylist[1:] = (mylist[1:] * (1+max_len//(len(mylist)-1)))[:max_len]
print(mylist)
print a, b, c, d

Finding the sum of matching components in two lists

I have two lists:
A = [1, 2, 3, 4, 5]
B = [6, 7, 8, 9, 10]
And I need to be able to find the sum of the nth terms from both lists i.e. 1+6, 2+7, 3+8 etc
Could someone please tell me how to refer to items in both lists at the same time?
I read somewhere that I could do Sum = a[i] + b[i] but I'm not convinced on how that would work.
>>> import operator
>>> map(operator.add, A, B)
[7, 9, 11, 13, 15]
just to demonstrate Pythons elegance :-)
Use a list comprehension and zip:
[a + b for (a,b) in zip(A,B)]
Are these questions homework? Or self-study?
If you know the lists will be the same length, you could do this:
AB = [A[i] + B[i] for i in range(len(A))]
In Python 2, you might want to use xrange instead of range if your lists are quite large. I think that's an explicit, simple, readable, obvious way to do it, but some might differ.
If the lists might be different lengths, you have to decide how you want to handle the extra elements. Let's say you want to ignore the extra elements of whichever list is longer. Here are three ways to do it:
AB = [A[i] + B[i] for i in range(min(len(A), len(B)))]
AB = map(sum, zip(A, B))
AB = [a + b for a, b in zip(A, B)]
The downside of using zip is that it will allocate a list of tuples, which can be a lot of memory if your lists are already large. Using for i in xrange with subscripting won't allocate all that memory, or you can use itertools.izip:
import itertools
AB = map(sum, itertools.izip(A, B))
If you instead want to pretend the shorter list is padded with zeros, using itertools.izip_longest is the shortest answer:
import itertools
AB = map(sum, itertools.izip_longest(A, B, fillvalue=0))
or
import itertools
AB = [a + b for a, b in itertools.izip_longest(A, B, fillvalue=0)]
Although Jazz's solution works for 2 lists, what if you have more than 2 lists? Here's a solution:
def apply_elementwise_function(elements_in_iterables, function):
elementwise_function = lambda x, y: itertools.imap(function, itertools.izip(x, y))
return reduce(elementwise_function, elements_in_iterables)
a = b = c = [1, 2, 3]
>>> list(apply_elementwise_function([a, b, c], sum))
[3, 6, 9]
Hi You can try this too:
>>>a=[1,2,3,4,5]
>>>b=[6,7,8,9,10]
>>>c=[]
>>>for i in range(0,5):
c.append(a[i]+b[i])
>>> c
[7, 9, 11, 13, 15]

Categories