Is there a way to get an alias for a part of a list in python?
Specifically, I want the equivalent of this to happen:
>>> l=[1,2,3,4,5]
>>> a=l
>>> l[0]=10
>>> a
[10, 2, 3, 4, 5]
But what I get is this:
>>> l=[1,2,3,4,5]
>>> a=l[0:2]
>>> l[0]=10
>>> a
[1, 2]
If numpy is an option:
import numpy as np
l = np.array(l)
a = l[:2]
l[0] = 10
print(l)
print(a)
Output:
[10 2 3 4 5]
[10 2]
slicing with basic indexing returns a view object with numpy so any change are reflected in the view object
Or use a memoryview with an array.array:
from array import array
l = memoryview(array("l", [1, 2, 3, 4,5]))
a = l[:2]
l[0]= 10
print(l.tolist())
print(a.tolist())
Output:
[10, 2, 3, 4, 5]
[10, 2]
You could embed each element into its own mutable data structure (like a list).
>>> l=[1,2,3,4,5]
>>> l = [[item] for item in l]
>>> l
[[1], [2], [3], [4], [5]]
>>> a = l[:2]
>>> a
[[1], [2]]
>>> l[0][0] = 10
>>> l
[[10], [2], [3], [4], [5]]
>>> a
[[10], [2]]
However, I recommend trying to come up with a solution to your original issue (whatever that was) that doesn't create issues of its own.
What you're looking for is a view of the original list, so that any modifications are reflected in the original list. This is doable with the array in the numpy package:
>>> import numpy
>>> x = numpy.array([1, 2, 3])
>>> y = x[2:]
>>> y[0] = 999
>>> x
array([ 1, 2, 999])
Related
This is related to leetcode problem #39.
I started with results.append(solution), which does not append properly to the list, and found in the solution that results.append(solution[:]) works. What's the difference between these two syntax?
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
results=[]
def backtracking(candidates,target,start,solution,results):
#print(start,target,solution,results)
if target<0:
return
if target==0:
results.append(solution[:])
return
for i in range(start,len(candidates)):
solution.append(candidates[i])
backtracking(candidates,target-candidates[i],i,solution,results)
solution.pop()
backtracking(candidates,target,0,[],results)
return results
a[:] will create a new list.
c.append(b) appends the list b to c.
Following code will help understand this better -
>>> a=[1,2,3]
>>> b=[4,5]
>>> c=[1,2,3]
>>> a.append(b) #append b
>>> c.append(b[:]) #create new list and append
>>> a
[1, 2, 3, [4, 5]]
>>> c
[1, 2, 3, [4, 5]]
>>> b
[4, 5]
>>> a[3][0]=99 #modify a
>>> a
[1, 2, 3, [99, 5]] #a modified
>>> b
[99, 5] #so does b
>>> c
[1, 2, 3, [4, 5]] #modify c
>>> c[3][1]=99
>>> c #c modified
[1, 2, 3, [4, 99]]
>>> b #original b did not get modified
[99, 5]
>>>
As you can see from the id of the objects, making a slice creates a new list
>>> a = [1, 2, 3]
>>> id(a)
2711680383816
>>> id(a[:])
2711683338696
whereas assigning the list directly refers to the same object
>>> b = a
>>> id(b)
2711680383816
a is a list and a[:] is a new list with all elements copied.
>>> a = [1, 2, 3]
>>> a == a[:]
True
>>> a is a[:]
False
Let's have another list b = ["a", "b"]. append adds whatever you give it to the end of a list. If you append another list, the reference to that list gets added and might lead to un expected behaviours:
>>> b.append(a)
>>> b
["a", "b", [1, 2, 3]]
>>> a[0] = "c"
>>> b
["a", "b", ["c", 2, 3]]
>>> b[2][1] = 42
>>> a
["c", 42, 3]
>>> a is b[2]
True
You can see, that after appending a, if you change an element in a, it also changes in b. This is because b only has a reference to a. To prevent that, you can instead do b.append(a[:]). This will copy the values in a, so when you then change values in a, values in b stay what they were when you copied them:
>>> b.append(a)
>>> b
["a", "b", [1, 2, 3]]
>>> a[0] = "c"
>>> b
["a", "b", [1, 2, 3]]
>>> b[2][1] = 42
>>> a
["c", 2, 3]
>>> a is b[2]
False
So in your question, using solution[:] makes sure that whatever has been added to the results doesn't change when solution.append happens on the next iteration of the for loop.
I want to multiply all the values in a list of lists in python:
input = 3*[[1,2,3],[3,2,1]]
so i get this output:
output = [[3,6,9],[9,6,3]]
i tried this:
l = [[1,2,3],[3,2,1]]
l = [i * 2 for i in x in l]
[[ 3 * i for i in inner ] for inner in outer]
>>> my_list = [[1,2,3],[3,2,1]]
>>> [map((3).__mul__, sublist) for sublist in my_list]
[[3, 6, 9], [9, 6, 3]]
You might consider using numpy arrays instead:
>>> import numpy as np
>>> a = np.array(my_list)
>>> a
array([[1, 2, 3],
[3, 2, 1]])
>>> 3*a
array([[3, 6, 9],
[9, 6, 3]])
I recently did an exam for university and I got asked what would be the output of this program:
def fun(x):
y=x
x.append(4)
print(str(x)+" "+str(y))
fun(["one","two",3,5.0])
I answered that the y list would be ["one","two", 3,5.0] and after appending 4 to it, the x list would be equal to the same but with a 4 at the end of it. To my surprise, when I printed both lists, they were equal even though the x list update was performed after establishing an equality between both lists. Why did this happen?
Thank you
You have given reference if list x to y. So any change in list x would also affect list y.
y=x
For example:
>>> x = ["one","two",3,5.0]
>>> y = x
>>> x[3] = 4
>>> x
['one', 'two', 3, 4]
>>> y
['one', 'two', 3, 4]
Here both x and y have same identity.
>>> x is y
True
>>> id(x)
3073118540L
>>> id(y)
3073118540L
You can better understand this using swampy module:
>>> from swampy.Lumpy import Lumpy
>>> lump = Lumpy()
>>> x = ["one","two",3,5.0]
>>> y = x
>>> x[3] = 4
>>> lump.object_diagram()
What you were expecting can be achieved by copying the list x to list y like this:
>>> x = ["one","two",3,5.0]
>>> y = x[:]
>>> x.pop()
5.0
>>> x
['one', 'two', 3]
>>> y
['one', 'two', 3, 5.0]
So by copying the content from x to y, they don't hold the same identity:
>>> id(x)
3073240428L
>>> id(y)
3073240588L
>>> x is y
False
Using swampy:
>>> from swampy.Lumpy import Lumpy
>>> lump = Lumpy()
>>> x = ["one","two",3,5.0]
>>> y = x[:]
>>> lump.draw_object()
>>> lump.object_diagram()
For better explanation visit here How do I copy an object in Python?
Actually x and y are labels that reference to object so when you assign y=x you crate 2 reference to one object , so when you change one of them you change the main object .
Also you may note that x , y are local variables when you made inplace changes like append you changed the main object , but if you use assignment python create a new object :
>>> def fun(x):
... y=x
... x=x+[3]
... print(str(x)+" "+str(y))
...
>>> fun(["one","two",3,5.0])
['one', 'two', 3, 5.0, 3] ['one', 'two', 3, 5.0]
in-place changes to objects do not classify names as locals; only actual name
assignments do. For instance, if the name L is assigned to a list at the top level of a
module, a statement L = X within a function will classify L as a local, but L.append(X)
will not. In the latter case, we are changing the list object that L references, not L itself—
L is found in the global scope as usual, and Python happily modifies it without requiring
a global (or nonlocal ) declaration. As usual, it helps to keep the distinction between
names and objects clear: changing an object is not an assignment to a name.(from learning python by mark lutz)
class A:
global L
L=[1,2]
def b(self):
L=[0,0]
return L
def c(self):
L.append(5)
return L
a=A()
print a.b()
print a.c()
result :
[0, 0]
[1, 2, 5]
Because list are mutable objects. see Python Data Model
In [1]: a = [1]
In [3]: b = a
In [4]: b
Out[4]: [1]
In [5]: b.append(2)
In [6]: a
Out[6]: [1, 2]
In [7]: b
Out[7]: [1, 2]
In [8]: id(a), id(b)
Out[8]: (140260765233376, 140260765233376)
Because the name y is bound to the same list as x
y = x
This is a great drawing of how that looks:
x y
| /
| /
["one", "two", 3, 5.0]
x.append(4)
x y
| /
| /
["one", "two", 3, 5.0, 4]
You can try following example. It will help you to get differences between assignment operator and method like copy(shallow), deepcopy.
>>> import copy
>>> l1 = [1,2, [1,2]]
>>> l1
[1, 2, [1, 2]]
#Create l2, l3, l4 by copy, deepcopy method and normal assignment.
>>> l2 = copy.copy(l1)
>>> l3 = copy.deepcopy(l1)
>>> l4 = l1
>>> l2
[1, 2, [1, 2]]
>>> l3
[1, 2, [1, 2]]
>>> l4
>>> [1, 2, [1, 2]]
#-----------------------Now Append value to l1
>>> l1.append(9)
>>> l1
[1, 2, [1, 2], 9]
>>> l2
[1, 2, [1, 2]]
>>> l3
[1, 2, [1, 2]]
>>> l4
>>> [1, 2, [1, 2], 9]
#-----------------------Now Append value to l1[2]
>>> l1[2].append(5)
>>> l1
[1, 2, [1, 2, 5], 9]
>>> l2
[1, 2, [1, 2, 5]]
>>> l3
[1, 2, [1, 2]]
>>> l4
>>> [1, 2, [1, 2, 5], 9]
#------------------------
I have a feeling that this is very easy but I can't quite figure out how to do it. Say I have a Numpy array
[1,2,3,4]
How do I convert this to
[[1],[2],[3],[4]]
In an easy way?
Thanks
You can use np.newaxis:
>>> a = np.array([1,2,3,4]
array([1, 2, 3, 4])
>>> a[:,np.newaxis]
array([[1],
[2],
[3],
[4]])
You can use numpy.reshape:
>>> import numpy as np
>>> a = np.array([1,2,3,4])
>>> np.reshape(a, (-1, 1))
array([[1],
[2],
[3],
[4]])
If you want normal python list then use list comprehension:
>>> a = np.array([1,2,3,4])
>>> [[x] for x in a]
[[1], [2], [3], [4]]
The most obvious way that comes to mind is:
>>> new = []
>>> for m in a:
new.append([m])
but this creates normal Python's list of lists, I'm not sure if this is what you want...
>>> A = [1,2,3,4]
>>> B = [[x] for x in A]
>>> print B
[[1], [2], [3], [4]]
I'm a Python beginner and I'm currently going through Zed Shaw's course "Learn Python the Hardway"
So, in exercise 32 we are told:
How do you make a 2-dimensional (2D) list?
That's a list in a list like this: [[1,2,3],[4,5,6]]
I did this:
# Extra 1
global_list = [[1, 2, 3]]
inside_list = []
for i in global_list[0]:
inside_list.append(i)
global_list.append(inside_list)
print(global_list)
But I’m not entirely convinced that's the correct way. My question is: Is there a way to get the same result without ever leaving the for i in.... loop?
I also tried this, to no avail.
global_list = [[1, 2, 3]]
inside_list = []
for i in global_list[0]:
inside_list.append(i)
global_list.append(inside_list)
print(global_list)
Thanks in advance for your answers.
Lists can be appended and inserted into a list just like any other object, e.g:
outer_list = []
print(outer_list)
inner_list1 = [1, 2, 3]
outer_list.append(inner_list1)
print(outer_list)
inner_list2 = [4, 5, 6]
outer_list.append(inner_list2)
print(outer_list)
I am not sure if you already went over list comprehension. However, one nice way of doing what you are doing is:
>>> global_list = [[1,2,3]]
>>> global_list.append([i + 3 for i in global_list[0]])
>>> print global_list
[[1, 2, 4], [4, 5, 6]]
The question was "How do you make a 2-dimensional (2D) list?". The answer given was "That's a list in a list like this: [[1,2,3],[4,5,6]]". Literally, that's the answer:
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> print a
[[1, 2, 3], [4, 5, 6]]
You can also do this:
>>> a = [[1, 2, 3]]
>>> a.append([4, 5, 6])
>>> a
[[1, 2, 3], [4, 5, 6]]
You don't need a for loop to append a list inside another list:
>>> a = [[1, 2, 3]]
>>> a[0]
[1, 2, 3]
>>> a.append(a[0])
>>> a
[[1, 2, 3], [1, 2, 3]]
However, this makes the second element of the list of lists the same as the first, so if you change one you change the other:
>>> a[0] is a[1]
True
>>> a[0][0] = 4
>>> a
[[4, 2, 3], [4, 2, 3]]
What you can do to make a copy of the list is list(a[0]):
>>> a = [[1, 2, 3]]
>>> a[0]
[1, 2, 3]
>>> a[0] is a[0]
True
>>> list(a[0])
[1, 2, 3]
>>> a[0] is list(a[0])
False
>>> a.append(list(a[0]))
>>> a
[[1, 2, 3], [1, 2, 3]]
>>> a[0] is a[1]
False
>>> a[0][0] = 4
>>> a
[[4, 2, 3], [1, 2, 3]]