I have a list of lists in the form:
list = [[3, 1], [3, 2], [3, 3]]
And I want to split it into two lists, one with the x values of each sublist and one with the y values of each sublist.
I currently have this:
x = y = []
for sublist in list:
x.append(sublist[0])
y.append(sublist[1])
But that returns this, and I don't know why:
x = [3, 1, 3, 2, 3, 3]
y = [3, 1, 3, 2, 3, 3]
By doing x = y = [] you are creating x and y and referencing them to the same list, hence the erroneous output. (The Object IDs are same below)
>>> x = y = []
>>> id(x)
43842656
>>> id(y)
43842656
If you fix that, you get the correct result.
>>> x = []
>>> y = []
>>> for sublist in lst:
x.append(sublist[0])
y.append(sublist[1])
>>> x
[3, 3, 3]
>>> y
[1, 2, 3]
Although, this could be made pretty easier by doing.
x,y = zip(*lst)
P.S. - Please don't use list as a variable name, it shadows the builtin.
When you say x = y = [], you're causing x and y to be a reference to the same list. So when you edit one, you edit the other. There is a good explanation here about how references work.
Therefore you can use your code if you say instead
x = []; y = []
You also might want to try zip:
lst = [[3, 1], [3, 2], [3, 3]]
x,y = zip(*lst)
And as Sukrit says, don't use list as a variable name (or int or str or what have you) because though it is a Python built-in (load up an interpreter and type help(list) - the fact that something pops up means Python has pre-defined list to mean something) Python will cheerfully let you redefine (a.k.a. shadow) it. Which can break your code later.
That's because when you construct x and y like x = y = [] then x and y point to the same list. If you want to make them different lists, you should declare them like
x = []
y = []
You are setting x = y = [] meaning x is pointing to y which is pointing to the list so whenever you append to one, you are appending to the other. Change the code to something like this:
x = []
y = []
for sublist in list:
x.append(sublist[0])
y.append(sublist[1])
You can do:
x = [i[0] for i in list]
y = [i[1] for i in list]
Related
I wrote a function that changes all instances of y to z in x (where x is a list) but somehow my code is not working. The outcome should have been [1, 'zzz', 3, 1, 'zzz', 3]. I attached my code below any help is appreciated. Thanks in advance.
x = [1, 2, 3, 1, 2, 3]
def changeThem(x,y,z):
replace = {y : z}
for key, value in replace.items():
x = x.replace(key, value)
print(x)
changeThem(x,2,'zzz')
A list does not have .replace() method. How about the following?
x = [1, 2, 3, 1, 2, 3]
def changeThem(x,y,z):
return [z if i == y else i for i in x]
print(changeThem(x, 2, 'zz'))
The function consists of just one line so defining this function might not be even necessary. But I am leaving it in case you would like to call it multiple times.
Your code yields an AttributeError. This is because list does not have a replace method. str has a replace method, so this might be where you're getting confused.
You could accomplish this with a very simple list comprehension:
x = [z if e == y else e for e in x]
Essentially, the above list comprehension states:
For every value e in the list x, replace it with z if the element is equal to y. Otherwise, just keep the element there.
It is also equivalent to the following:
result = []
for e in x:
if e == y:
result.append(z)
else:
result.append(x)
How would you short these two list comprehension to one line? I would like to code as one line. My way seems too long. I feel like there is another way to code it.
y = [array[i][0] for i in range(len(array))]
x = [i for i in range(len(array))]
x, y = [i for i in range(len(array))], [array[i][0] for i in range(len(array))]
Assuming you want to extract the first column of a 2D list along with it's indices, you'd use enumerate with inverse-zip unpacking:
array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
x, y = zip(*enumerate([r[0] for r in array]))
print(x)
(0, 1, 2)
print(y)
(1, 4, 7)
x is the index, and y is the row vector. As seen above, this method results in your data being extracted out as tuples (not lists), and will fail when array is empty.
So, as #user2357112 said in their comment, please don't endeavour to shove all your code into one line – do it only when it can be done and makes sense to do so.
Furthermore, to extend the discussion in comments, the best way to do this would be to follow a 2-step approach as shown by #Rakesh in their answer:
x = list(range(len(array)))
y = [r[0] for r in array]
print(x)
[0, 1, 2]
print(y)
[1, 4, 7]
This doesn't suffer from the drawbacks mentioned above.
This should help
x = range(len(array)) #range returns list
y = [i[0] for i in array] #you can access the element in the list without range or len
x, y = list(map(list, zip(*[(i, r[0]) for i, r in enumerate(a)]))) or ([], [])
disclaimer: I think it's a situation where one-liner-ness is a bad thing.
I have been trying this a lot.
>>> x = [4,5]
>>> y = x.append(7)
>>> print y
None
>>>print x
[4, 5, 7]
How is this possible?
When I trying storing the values in the new list y and the print it, it results in None and it also changes the current list `x.
Is there any other way to do this in Python?
Because the function append() modifies the list and returns None.
One of the best practices to do what you want to do is by using + operator.
Let's take your example :
>>> x = [4, 5]
>>> y = x + [7]
>>> x
[4, 5]
>>> y
[4, 5, 7]
The + operator creates a new list and leaves the original list unchanged.
This is possible because x.append() is a method of list x that mutates the list in-place. There is no need for a return value as all the method needs to do is perform a side effect. Therefore, it returns None, which you assign your variable y.
I think you want to either create a copy of x and append to that:
y = x[:]
y.append(7)
or assign y the result of a list operation that actually creates a new list:
y = x + [7]
You can do
x = [4,5]
y = x + [7]
# x = [4, 5]
# y = [4, 5, 7]
The y is None because the append() method doesn't return the modified list (which from your code you are expecting).
So you can either split the statement,
y = x.append(7)
into
x.append(7)
y = x
OR use,
y = x + [7]
The second statement is more cleaner and creates a new list from x.
Just a note: Updating y won't make any updates in x as in the first statement it does. If you want to avoid this use copy.copy
Using Extend,
x = [3,4]
y =[]
y.extend(x+[7])
print(x, y)
produces output :
[3, 4] [3, 4, 7]
[Program finished]
I have a list L of objects (for what it's worth this is in scons). I would like to create two lists L1 and L2 where L1 is L with an item I1 appended, and L2 is L with an item I2 appended.
I would use append but that modifies the original list.
How can I do this in Python? (sorry for the beginner question, I don't use the language much, just for scons)
L1 = L + [i1]
L2 = L + [i2]
That is probably the simplest way. Another option is to copy the list and then append:
L1 = L[:] #make a copy of L
L1.append(i1)
L1=list(L)
duplicates the list. I guess you can figure out the rest :)
You can make a copy of your list
>>> x = [1, 2, 3]
>>> y = list(x)
>>> y.append(4)
>>> y
[1, 2, 3, 4]
>>> z = list(x)
>>> z.append(5)
>>> z
[1, 2, 3, 5]
or use concatenation, which will make a new list
>>> x = [1, 2, 3]
>>> y = x + [4]
>>> z = x + [5]
>>> y
[1, 2, 3, 4]
>>> z
[1, 2, 3, 5]
The former is probably a touch more idiomatic/common, but the latter works fine in this case. Some people also copy using slicing (x[:] makes a new list with all the elements of the original list x referred to) or the copy module. Neither of these are awful, but I find the former a touch cryptic and the latter a bit silly.
Can someone explain why the example with integers results in different values for x and y and the example with the list results in x and y being the same object?
x = 42
y = x
x = x + 1
print x # 43
print y # 42
x = [ 1, 2, 3 ]
y = x
x[0] = 4
print x # [4, 2, 3]
print y # [4, 2, 3]
x is y # True
The best explanation I ever read is here:
http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables
Because integers are immutable, while list are mutable. You can see from the syntax. In x = x + 1 you are actually assigning a new value to x (it is alone on the LHS). In x[0] = 4, you're calling the index operator on the list and giving it a parameter - it's actually equivalent to x.__setitem__(0, 4), which is obviously changing the original object, not creating a new one.
If you do y = x, y and x are the reference to the same object. But integers are immutable and when you do x + 1, the new integer is created:
>>> x = 1
>>> id(x)
135720760
>>> x += 1
>>> id(x)
135720748
>>> x -= 1
>>> id(x)
135720760
When you have a mutable object (e.g. list, classes defined by yourself), x is changed whenever y is changed, because they point to a single object.
That's because when you have a list or a tuple in python you create a reference to an object.
When you say that y = x you reference to the same object with y as x does.
So when you edit the object of x y changes with it.
As the previous answers said the code you wrote assigns the same object to different names such aliases.
If you want to assign a copy of the original list to the new variable (object actually)
use this solution:
>>> x=[1,2,3]
>>> y=x[:] #this makes a new list
>>> x
[1, 2, 3]
>>> y
[1, 2, 3]
>>> x[0]=4
>>> x
[4, 2, 3]
>>> y
[1, 2, 3]