python, how to make/change a list with lists - python

So more or less i am trying to figure this out:
a = [1,2]
b = [3,4,5]
c = [6,7,8,9]
z = [a,b,c]
def raiseInt():
x = 0
for int in z:
a[x] + 1
b[x] + 1
c[x] + 1
I'm trying to increase every int in every list by 1

I will try to make my code self-explanatory. Note the name of each object
a = [1,2]
b = [3,4,5]
c = [6,7,8,9]
z = [a,b,c]
def raiseInt(list_to_increase_by_1):
#x = 0 we may actually do not need to assign this variable.
for sublist in list_to_increase_by_1:
for index_of_element, element in enumerate(sublist):
sublist[index_of_element] += 1
return list_to_increase_by_1
print raiseInt(z)
best practice related details
As you can see from Moinuddin Quadri's comments, I do not use the variable (iteratively assigned) element. In this case, the convention is about naming it _, so as to explicit that tha variable is actually not used.Which thus turns the code into
def raiseInt(list_to_increase_by_1):
for sublist in list_to_increase_by_1:
for index_of_element, _ in enumerate(sublist):
sublist[index_of_element] += 1
return list_to_increase_by_1
more best practice related details
As can be read from Paul Ronney's comment
[strictly doing as above] is contrary to python best practice, that any in place modifying function returns None. It should do one or the other and if the choice is to return it should return a copy and leave the original intact
Thus, folowing this comment implies to define raiseInt as an in place modifying function, as follows
def raiseInt(list_to_increase_by_1):
for sublist in list_to_increase_by_1:
for index_of_element, _ in enumerate(sublist):
sublist[index_of_element] += 1
I.e. with the function returning None

A very simple way to do this
a = [1,2]
b = [3,4,5]
c = [6,7,8,9]
z = [a,b,c]
def raiseInt():
for L in z:
for i in range(len(L)):
L[i] +=1
print(z)
raiseInt()
print(z)
output
[[1, 2], [3, 4, 5], [6, 7, 8, 9]]
[[2, 3], [4, 5, 6], [7, 8, 9, 10]]
Iterate over the lists in z and then iterate for a number of times equal to the lists length and increment each element.
You could certainly improve your function by passing the lists to be operated on in as a parameter. This would make your function more generally useful, as it is, it can only operate on that one list called z.

def raiseInt():
for v in z:
for i in range(len(v)):
v[i] += 1;

Related

Loop to select specific numbers from a given list

My problem is that in python i have a list of 1000 numbers. I want to select first 20 and store in "A" (another list) and next 30 in "B"(another list), again next 20 in "A", next 30 in "B" untill the list ends. How to do that? Can anyone help please?
You could use two nested list comprehension for this:
nums = list(range(2000))
A = [x for i in range( 0, len(nums), 50) for x in nums[i:i+20]]
B = [x for i in range(20, len(nums), 50) for x in nums[i:i+30]]
That means (for A): Starting at index 0, 50, 100 etc., take the next 20 elements and add them to A. Analogous for B. You might also use itertools.islice for the nums[i:i+n] part to avoid creating a bunch of temporary sub-lists.
Of course, this assumes that A and B do not already exist. If they do, and you want to add elements to them, use a regular loop and extend (not tested):
for i in range(0, len(nums), 50):
A.extend(nums[i :i+20])
B.extend(nums[i+20:i+50])
You do not have to check the indices again within the loop; if i+20 is already bigger than the last index in the list, B will just get extended with the empty list in the last step.
I made a function that can do what you're asking
def split_list(lst, gap1, gap2):
tmp = lst.copy()
out1, out2 = [], []
while tmp:
out1.extend(tmp[:gap1])
tmp = tmp[gap1:]
out2.extend(tmp[:gap2])
tmp = tmp[gap2:]
return out1, out2
gap1 and gap2 are the length of each subset you want to store, so in your case gap1=20 and gap2=30.
Example
numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
A, B = split_list(numbers, 2, 3)
print(A)
print(B)
Let's first define the followings:
A = [] #empty list
B = [] #empty list
And let's call your first list (that includes 1000 numbers), as my_list.
Then, a simple solution can be as following:
counter = 0
c_a = 2
c_b = 3
while (counter < len(my_list)):
A = A + my_list[counter:counter+c_a]
B = B + my_list[counter+c_a : counter + c_a + c_b]
counter = counter + c_a + c_b
I suggest generating a 2D nested list, which contains sublists each having 20 elements in it. Here is a one line way of doing that with a list comprehension:
x = range(1, 1001)
output = [x[idx*20:(idx*20 + 20)] for idx in range(0, len(x) / 20)]
Here is a version which operates on a smaller set of data, for demonstration purposes:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9]
output = [x[idx*3:(idx*3 + 3)] for idx in range(0, len(x) / 3)]
print(output) # [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

How to perform a pairwise swap of a list?

I want to write a small code in python that Swap Elements in a list this program will accept a list, and will return a list that exchanges the positions of each pair of adjacent elements: positions 0 and 1, positions 2 and 3, and so on. If the list has an odd number of elements, then the element in the last position stays “in place”.
Before: [1,2,3,4,5]
After: [2,1,4,3,5]
This looks unpythonic. What is the Python way to do it?
Here is a neat one, if you are always guaranteed to have even numbers:
nums = [1,2,3,4,5,6]
print([nums[i^1] for i in range(len(nums))])
>>[2, 1, 4, 3, 6, 5]
Explanation:
print (0^1) #1
print (1^1) #0
print (2^1) #3
print (3^1) #2
print (4^1) #5
print (5^1) #4
As a refresher, the XOR has the following effect:
A B | Output
---------------
0 0 0
0 1 1
1 0 1
1 1 0
And the official description: Each bit of the output is the same as the corresponding bit in x if that bit in y is 0, and it's the complement of the bit in x if that bit in y is 1.
Most pythonic way:
def swappairwise(a):
l = len(a)&~1
a[1:l:2],a[:l:2] = a[:l:2],a[1:l:2]
Building on the answer above from #Arpegius, here a, hopefully, somewhat more readable solution. Uses the same approach.
def swap_list_pairwise(lis):
"""Pairwise swap of all elements in a list.
If the number of elements is odd, the leftover element
stays at its place.
"""
length = len(lis)
# Stop at second last if length is odd, otherwise use full list.
end = length - 1 if length % 2 else length
lis[1:end:2], lis[:end:2] = lis[:end:2], lis[1:end:2]
If you want "pythonic", try "How do you split a list into evenly sized chunks in Python?", followed by a map() that reverses every chunk. May not be too performant, though.
(Oh, forgot the flattening of the list at the end)
Here is a way:
def pairwise_swap(iterable):
for i, value in enumerate(iterable):
if i % 2 == 0:
saved = value
else:
yield value
yield saved
>>> list(pairwise_swap(range(10)))
[1, 0, 3, 2, 5, 4, 7, 6, 9, 8]
Nice approach by #Alok above. This should fix the missing last
element if the number of elements is odd.
def pairwise_swap(iterable):
"""Pairwise swap of all elements in an iterable.
If the number of elements is odd, the leftover element
stays at its place.
"""
for i, value in enumerate(iterable):
if i % 2 == 0:
saved = value
else:
yield value
yield saved
# Don't forget the last element if `iterable` has an odd
# number of elements. Since counting starts a zero, we need
# to test if `i` is even.
if iterable and i % 2 == 0:
yield value
How about trying this one out?
>>> l = [1,2,3,4,5,6]
>>> pl = [l[i:i+2] for i in range(0,len(l),2)]
>>> pl
[[1, 2], [3, 4], [5, 6]]
>>> for i in pl:
... i[0],i[1] = i[1],i[0]
... print i
...
[2, 1]
[4, 3]
[6, 5]
>>> pl
[[2, 1], [4, 3], [6, 5]]
>>>
>>> zpl = [i for sublist in pl for i in sublist]
>>> zpl
[2, 1, 4, 3, 6, 5]
>>>
I tried to resolve in the easiest way out.
It will work for both even and odd elements. if list elements are even
first part will work if not else will do his task.
a = list(input("Put your list here: "))
len_a = len(a)
last_element = len_a-1
result = 0
if len_a % 2==0:
for i in range(0, len(a), 2):
a[i], a[i + 1] = a[i + 1], a[i]
print("its if",a)
else:
a_n = a.pop()
for i in range(0, len(a), 2):
a[i], a[i + 1] = a[i + 1], a[i]
a.insert(0,a_n)
# a.insert(last_element,a_n) if you want last element remain unmodified
print("its else:",a)
This is what worked for me. Hopefully, it can help others. I think about using boxes. The value in the first position needs a temporary place to be before it can be swapped, so I assign it to x and then make the swap. Incrementing by 2 will skip over the last element, so it's okay with odd-numbered lists as well.
a = [int(s) for s in input().split()]
i = 0
while i in range(0, len(a) - 1):
x = a[i]
a[i] = a[i + 1]
a[i + 1] = x
i += 2
print(a)
Found this to be much simpler solution and handels the list with odd elements
elements = list(map(int,input().split()))
swap = []
i = 0
while i < len(elements):
if i+1 < len(elements):
swap.append(elements[i+1])
swap.append(elements[i])
else:
swap.append(elements[-1])
i = i+2
print(swap)

Python Variable assignment in a for loop

I understand that in Python regular c++ style variable assignment is replaced by references to stuff ie
a=[1,2,3]
b=a
a.append(4)
print(b) #gives [1,2,3,4]
print(a) #gives [1,2,3,4]
but I'm still confused why an analogous situation with basic types eg. integers works differently?
a=1
b=a
a+=1
print(b) # gives 1
print(a) # gives 2
But wait, it gets even more confusing when we consider loops!
li=[1,2,3]
for x in li:
x+=1
print(li) #gives [1,2,3]
Which is what I expected, but what happens if we do:
a,b,c=1,2,3
li=[a,b,c]
for x in li:
x+=1
print(li) #gives [1,2,3]
Maybe my question should be how to loop over a list of integers and change them without map() as i need a if statement in there. The only thing I can come up short of using
for x in range(len(li)):
Do stuff to li[x]
is packaging the integers in one element list. But there must be a better way.
Well, you need to think of mutable and immutable type.
For a list, it's mutable.
For a integer, it's immutable, which means you will refer to a new object if you change it. When a+=1 is executed, a will be assigned a new object, but b is still refer to the same one.
a=[1,2,3]
b=a
a.append(4)
print(b) #[1,2,3,4]
print(a) #[1,2,3,4]
Here you are modifying the list. The list content changes, but the list identity remains.
a=1
b=a
a+=1
This, however, is a reassignment. You assign a different object to a.
Note that if you did a += [4] in the 1st example, you would have seen the same result. This comes from the fact that a += something is the same as a = a.__iadd__(something), with a fallback to a = a.__add__(something) if __iadd__() doesn't exist.
The difference is that __iadd__() tries to do its job "inplace", by modifying the object it works on and returning it. So a refers to the same as before. This only works with mutable objects such as lists.
On immutable objects such as ints __add__() is called. It returns a different object, which leads to a pointing to another object than before. There is no other choice, as ints are immutable.
a,b,c=1,2,3
li=[a,b,c]
for x in li:
x+=1
print(li) #[1,2,3]
Here x += 1 means the same as x = x + 1. It changes where x refers to, but not the list contents.
Maybe my question should be how to loop over a list of integers and change them without >map() as i need a if statement in there.
for i, x in enumerate(li):
li[i] = x + 1
assigns to every list position the old value + 1.
The important thing here are the variable names. They really are just keys to a dictionary. They are resolved at runtime, depending on the current scope.
Let's have a look what names you access in your code. The locals function helps us: It shows the names in the local scope (and their value). Here's your code, with some debugging output:
a = [1, 2, 3] # a is bound
print(locals())
for x in a: # a is read, and for each iteration x is bound
x = x + 3 # x is read, the value increased and then bound to x again
print(locals())
print(locals())
print(x)
(Note I expanded x += 3 to x = x + 3 to increase visibility for the name accesses - read and write.)
First, you bind the list [1, 2, 3]to the name a. Then, you iterate over the list. During each iteration, the value is bound to the name x in the current scope. Your assignment then assigns another value to x.
Here's the output
{'a': [1, 2, 3]}
{'a': [1, 2, 3], 'x': 4}
{'a': [1, 2, 3], 'x': 5}
{'a': [1, 2, 3], 'x': 6}
{'a': [1, 2, 3], 'x': 6}
6
At no point you're accessing a, the list, and thus will never modify it.
To fix your problem, I'd use the enumerate function to get the index along with the value and then access the list using the name a to change it.
for idx, x in enumerate(a):
a[idx] = x + 3
print(a)
Output:
[4, 5, 6]
Note you might want to wrap those examples in a function, to avoid the cluttered global namespace.
For more about scopes, read the chapter in the Python tutorial. To further investigate that, use the globals function to see the names of the global namespace. (Not to be confused with the global keyword, note the missing 's'.)
Have fun!
For a C++-head it easiest tho think that every Python object is a pointer. When you write a = [1, 2, 3] you essentially write List * a = new List(1, 2, 3). When you write a = b, you essentially write List * b = a.
But when you take out actual items from the lists, these items happen to be numbers. Numbers are immutable; holding a pointer to an immutable object is about as good as holding this object by value.
So your for x in a: x += 1 is essentially
for (int x, it = a.iterator(); it->hasMore(); x=it.next()) {
x+=1; // the generated sum is silently discarded
}
which obviously has no effect.
If list elements were mutable objects you could mutate them exactly the way you wrote. See:
a = [[1], [2], [3]] # list of lists
for x in a: # x iterates over each sub-list
x.append(10)
print a # prints [[1, 10], [2, 10], [3, 10]]
But unless you have a compelling reason (e.g. a list of millions of objects under heavy memory load) you are better off making a copy of the list, applying a transformation and optionally a filter. This is easily done with a list comprehension:
a = [1, 2, 3, 0]
b = [n + 1 for n in a] # [2, 3, 4, 1]
c = [n * 10 for n in a if n < 3] # [10, 20, 0]
Either that, or you can write an explicit loop that creates another list:
source = [1, 2, 3]
target = []
for n in source:
n1 = <many lines of code involving n>
target.append(n1)
Your question has multiple parts, so it's going to be hard for one answer to cover all of them. glglgl has done a great job on most of it, but your final question is still unexplained:
Maybe my question should be how to loop over a list of integers and change them without map() as i need a if statement in there
"I need an if statement in there" doesn't mean you can't use map.
First, if you want the if to select which values you want to keep, map has a good friend named filter that does exactly that. For example, to keep only the odd numbers, but add one to each of them, you could do this:
>>> a = [1, 2, 3, 4, 5]
>>> b = []
>>> for x in a:
... if x%2:
... b.append(x+1)
Or just this:
>>> b = map(lambda x: x+1, filter(lambda x: x%2, a))
If, on the other hand, you want the if to control the expression itself—e.g., to add 1 to the odd numbers but leave the even ones alone, you can use an if expression the same way you'd use an if statement:
>>> for x in a:
... if x%2:
... b.append(x+1)
... else:
... b.append(x)
>>> b = map(lambda x: x+1 if x%2 else x, a)
Second, comprehensions are basically equivalent to map and filter, but with expressions instead of functions. If your expression would just be "call this function", then use map or filter. If your function would just be a lambda to "evaluate this expression", then use a comprehension. The above two examples get more readable this way:
>>> b = [x+1 for x in a if x%2]
>>> b = [x+1 if x%2 else x for x in a]
You can do something like this: li = [x+1 for x in li]

How to re-assign items in a list in Python?

I want to re-assign each item in a list in Python.
In [20]: l = [1,2,3,4,5]
In [21]: for i in l:
....: i = i + 1
....:
....:
But the list didn't change at all.
In [22]: l
Out[22]: [1, 2, 3, 4, 5]
I want to know why this happened. Could any body explain the list iterating in detail? Thanks.
You can't do it like that, you are merely changing the value binded to the name i. On each iteration of the for loop, i is binded to a value in the list. It is not a pointer in the sense that by changing the value of i you are changing a value in the list. Instead, as I said before, it is simply a name and you are just changing the value that name refers to. In this case, i = i + 1, binds i to the value i + 1. So you aren't actually affecting the list itself, to do that you have to set it by index.
>>> L = [1,2,3,4,5]
>>> for i in range(len(L)):
L[i] = L[i] + 1
>>> L
[2, 3, 4, 5, 6]
Some pythonistas may prefer to iterate like this:
for i, n in enumerate(L): # where i is the index, n is each number
L[i] = n + 1
However you can easily achieve the same result with a list comprehension:
>>> L = [1,2,3,4,5]
>>> L = [n + 1 for n in L]
>>> L
[2, 3, 4, 5, 6]
For more info: http://www.effbot.org/zone/python-objects.htm
This is because of how Python handles variables and the values they reference.
You should modify the list element itself:
for i in xrange(len(l)):
l[i] += 1
>>> a = [1, 2, 3, 4, 5]
>>> a = [i + 1 for i in a]
>>> a
[2, 3, 4, 5, 6]
Initially i is a pointer to the item inside the list, but when you reassign it, it will point to the new number, that is why the list will not be changed.
For a list of mutable objects it would work:
class Number(object):
def __init__(self,n):
self.n=n
def increment(self):
self.n+=1
def __repr__(self):
return 'Number(%d)' % self.n
a = [Number(i) for i in xrange(5)]
print a
for i in a:
i.increment()
print a
But int are not mutable, when you do an operation on them you get a new int object, and that is why it doesn't work in your case.

in python what's the relation between the loop variable and the elements in list when we do for loop?

Here are several list: a, b, etc
I want to make some change of them respectively, but I'm confused with the behavier of for loop.
for example:
if we do
a, b = range(5), range(5,10)
for x in [a, b]: x += [0]
print(a,b)
we get
([0, 1, 2, 3, 4, 0], [5, 6, 7, 8, 9, 0])
a,b are modified.
but if we do
a, b = range(5), range(5,10)
for x in [a, b]: x = x + [0]
print(a,b)
we get
([0, 1, 2, 3, 4], [5, 6, 7, 8, 9])
a,b aren't modified.
I'm confused, what's the relation between x and a? When or how I can modify the value of a with x?
And by the way, what's the difference between a+=b and a=a+b?
Anyway, I find a solution that we can do like this
a, b = range(5), range(5,10)
lis = [a, b]
for i, x in enumerate(lis):
lis[i] = ...
then we can modify values of a & b. But this method need make a extra list.
And there's anther solution
for x in ['a', 'b']:
exec(x + '=' + x + '+ ...')
And an easier solution
a, b = range(5), range(5,10)
for x in [a, b]: x[:] = x + [0]
print(a,b)
We will find a,b are modified :)
The relation is the same as with all variable binding in Python. The name is bound to the value. The differences you are seeing are because you are doing different things, sometimes, operating on the value and sometimes on the name.
For lists, += extends the list in-place --- that is, it modifies the original list. Thus the modifications are visible everywhere that list is used.
When you do x = x + [0], you rebind the name x to a new list (formed by adding the old list plus [0]). This does not modify the original list, so other places that use that list will not see the change.
If you search around for Python questions on "variables", "names", "values", "call by refernce" and the like you will find other discussions of this. Here is a question discussing a similar issue in the context of function-parameter binding. The principles are the same in for-loop variable binding.
The line:
x += something
changes a list in place, while:
x = x + something
creates a brand new list by joining x and something.
It's no different to the following simplified demonstration:
>>> a = [7] # The object is [7], name a is connected to it.
>>> x = a # Now name x is also connected.
>>> x += [2] # Here we change the backing object (behind a AND x).
>>> a # So that both names seem to change.
[7, 2]
>>> x
[7, 2]
>>> a = [7] # The object is [7], name a is connected to it.
>>> x = a # Now name x is also connected.
>>> x = x + [2] # Here we create a NEW object from the old one, and connect x.
>>> a # So a is unchanged.
[7]
>>> x # But x IS changed.
[7, 2]
This was the hardest thing I had to get used to in Python, the fact that names and the objects that names refer to are quite disparate, and can often act in surprising ways. It's also one of its most beautiful features once you nut it out.
I eventually just started thinking that names were C pointers and all objects were on the heap (since that was where I have my expertise). There may be better ways to think of it, though I've never found any for me.

Categories