list in python behaviour - list

I have a list my_list created as mylist = [[]]*5
now I want to add an integer say 4 to the third list in my_list
my_list[2].append(4)
When I print out my_list i see that every list in my_list has the integer 4 added to it.
>>> my_list = [[]]*5
>>> my_list[2].append(4)
>>> my_list
[[4], [4], [4], [4], [4]]
is there a way to just have 4 added to the 3rd list?
expected: [[],[],[4],[],[]]
actual: [[4],[4],[4],[4],[4]]

figured out the answer.
my_list = [[] for i in xrange(5)]
should do the trick

Well my understanding of what is going on is that when you run [[]] it just creates multiple references to one initialized list. I believe [[] for i in range(5)] is what you are looking for; it initializes different lists inside the parent list. Hope this helps!

TL,DR:
mylist = [list() for i in xrange(5)]
When python meets mylist = [[]]*5, it will create one entity list in your memory, and append 5 references of this only one list to mylist.
It is equal to this:
single_list = []
mylist = [single_list, single_list, single_list, single_list, single_list]
So, if you append 4 to the third list, 4 is now in the single_list, and since all of the 5 references is to the same single_list, it looks like all of the 5 lists contains 4.

Related

python 3, comparing elements of two lists of lists

I'm trying to compare elements of 2 lists of lists in python. I want to create a new list (ph) which has a 1 if elements of lists from the 1st list of lists are in the elements of the 2nd list of lists.
However, this seems to compare the whole list and not individual elements. The code is below. Many thanks for the help! :)
import numpy as np
import pandas as pd
abc = [[1,800000,3],[4,5,6],[100000,7,8]]
l = [[
[i for i in range(0, 100000)],
[i for i in range(200000,300000)],
[i for i in range(400000,500000)],
[i for i in range(600000,700000)],
[i for i in range(800000,900000)],
[i for i in range(1000000,1100000)]
]]
ph = []
for i in abc:
for j in l:
if l[0] == abc[0]:
ph.append(1)
else:
ph.append(0)
print(ph)
The goal of your problem is somewhat unclear to me. Correct me if I'm wrong but what you want is: for each sublist of abc, get a boolean describing if all its elements are anywhere in l. Is that it ?
If it is indeed the case, here's my answer.
First of all, your second list is not a list of lists but a list of lists of lists. Hence, I removed a nested list in my code.
abc = [[1,800000,3],[4,5,6],[100000,7,8]]
L = [
[i for i in range(0, 100000)],
[i for i in range(200000,300000)],
[i for i in range(400000,500000)],
[i for i in range(600000,700000)],
[i for i in range(800000,900000)],
[i for i in range(1000000,1100000)]
]
flattened_L = sum(L, [])
print(
list(map(lambda sublist: all(x in flattened_L for x in sublist), abc))
)
# returns [True, True, False]
My code first flattens L so that is becomes easy to check whether any element is in it or not. Then, for each sublist in abc, it checks if all elements are in this flattened list.
Note: my code returns a list of boolean. If you absolutely need integers value (0 and 1), which you shouldn't, you can wrap int around all.

How to interpret fancy for loop in Python 2.7?

How does this line look as a regular 'for' loop?
inputList = [int(a) for a in inputList]
What are the advantages to writing a 'for' loop this way as opposed to the more vanilla way?
You are talking about Python syntax which is known as list comprehension. Check out this link
See the following example:
No list comprehension:
list = []
for i in range (0, 9):
if i > 5:
list.append(i)
Output: [6, 7, 8]
List comprehension:
newList = [i for i in list if i>=5]
Output: [6, 7, 8]
Why use list comprehension
List comprehension compressed 4 lines of code into 1 line of code
new_list = []
for a in inputList:
new_list.append(int(a))
inputList = new_list
Probably something like this.
I did something like this and it worked:
enteredList = []
for a in inputList:
enteredList.append(int(a))

Reference Equality Python

I want to have a functionality like below. I have tried many things but still unable to achieve it.
>>> a, b = [1], [2]
>>> k = [a, a, b]
>>> k
[[1], [1], [2]]
Now as expected, if I change the second value the first value will be changed automatically.
>>> k[0][0] = 3
>>> k
[[3], [3], [2]]
You see how changing one value affects the other.
Now I want to somehow link the third element with the first two such that whenever I change any of the three elements, every element that it's linked to changes. I want to have the following behavior:
>>> *Do something to link k[1] or k[0] with k[2]*
>>> k[-1][0] = 4
>>> k
>>> [[4], [4], [4]]
I have tried doing the following and failed as you can see below:
>>> b = a
>>> k
>>> [[3], [3], [2]]
Please help me achieve the above.
The real problem I want to solve:
I am implementing min-cut algorithm. In this algorithm I need to merge two vertices at every step. I am trying doing this by linking the two vertices together which I want to merge.
Is this what you want?
a,b = [1],[2]
k = [a,a,b] # store references to lists a and b
print(k)
k[0][0] = 3 # change the first cell's list's first element
print(k) # second cell changes as well since it references same list
k[-1] = k[0] # store the first cell's reference in the last cell. All reference the same list 'a' now.
k[1][0] = 4
print(k)
Output:
[[1], [1], [2]]
[[3], [3], [2]]
[[4], [4], [4]]

Find and delete list elements if matching a string

I have a list of strings stringlist = ["elementOne" , "elementTwo" , "elementThree"] and I would like to search for elements that contain the "Two" string and delete that from the list so my list will become stringlist = ["elementOne" , "elementThree"]
I managed to print them but don't really know how to delete completely from the list using del because i don't know the index or by using stringlist.remove("elementTwo") because I don't know the exact string of the element containing "Two"
My code so far:
for x in stringlist:
if "Two" in x:
print(x)
Normally when we perform list comprehension, we build a new list and assign it the same name as the old list. Though this will get the desired result, but this will not remove the old list in place.
To make sure the reference remains the same, you must use this:
>>> stringlist[:] = [x for x in stringlist if "Two" not in x]
>>> stringlist
['elementOne', 'elementThree']
Advantages:
Since it is assigning to a list slice, it will replace the contents with the same Python list object, so the reference remains the same, thereby preventing some bugs if it is being referenced elsewhere.
If you do this below, you will lose the reference to the original list.
>>> stringlist = [x for x in stringlist if "Two" not in x]
>>> stringlist
['elementOne', 'elementThree']
So to preserve the reference, you build the list object and assign it the list slice.
To understand the subtle difference:
Let us take a list a1 containing some elements and assign list a2 equal to a1.
>>> a1 = [1,2,3,4]
>>> a2 = a1
Approach-1:
>>> a1 = [x for x in a1 if x<2]
>>> a1
[1]
>>> a2
[1,2,3,4]
Approach-2:
>>> a1[:] = [x for x in a1 if x<2]
>>> a1
[1]
>>> a2
[1]
Approach-2 actually replaces the contents of the original a1 list whereas Approach-1 does not.
You can use enumerate to get the index when you iterate over your list (but Note that this is not a pythonic and safe way to modify your list while iterating over it):
>>> for i,x in enumerate(stringlist):
... if "Two" in x:
... print(x)
... del stringlist[i]
...
elementTwo
>>> stringlist
['elementOne', 'elementThree']
But as a more elegant and pythonic way you can use a list comprehension to preserve the elements that doesn't contains Two :
>>> stringlist = [i for i in stringlist if not "Two" in i]
>>> stringlist
['elementOne', 'elementThree']
Doing this will help you
for i,x in enumerate(stringlist):
if "Two" in x:
del stringlist[i]
or
newList = []
for x in stringlist:
if "Two" in x:
continue
else
newList.append(x)
Using regex,
import re
txt = ["SpainTwo", "StringOne"]
for i in txt:
x = re.search(r"Two", i)
if x:
temp_list = temp_list + [x.string] if "temp_list" in locals() else [x.string]
print(temp_list)
gives
['SpainTwo']
print(list(filter(lambda x: "Two" not in x, ["elementOne" , "elementTwo" , "elementThree", "elementTwo"])))
Using lambda, if you are only looking to print.
if you want to check for multiple string and delete if detected from list of string use following method
List_of_string = [ "easyapplyone", "appliedtwotime", "approachednone", "seenthreetime", "oneseen", "twoapproached"]
q = ["one","three"]
List_of_string[:] = [x for x in List_of_string if any(xs not in x for xs in q)]
print(List_of_string)
output:[ "approachednone", "seenthreetime"]
Well this was pretty simple - sorry for all the trouble
for x in stringlist:
if "Two" in x:
stringlist.remove(x)

python: copying list and appending in one step

I have a strange reaction of python (using 2.7) here. I am trying to copy a list and append something to the copy at the same time. Here is the code:
myList = [1]
>>> newList = list(myList).append(2)
>>> newList
>>> print newList
None
>>> type(newList)
<type 'NoneType'>
Why is it that I get a NoneType object instead of my appended list-copy?
I stumbled over this when I tried to take a list1 copy it as many times as a list2 and append the elements of list2 to the ones in list1.
>>> list1 = [1,2]
>>> list2 = [3,4]
>>> list3 = [list(list1).append(i) for i in list2]
>>> list3
[None, None]
I expected:
>>> list3
[[1,2,3],[1,2,4]]
Why is it None,None?
Thanks a lot!
You can do this by adding a extra line:
myList=[1]
myList.append(2);newList=myList
You can also extend (append )list directly like:
list1 = [1,2]
list2 = [3,4]
list1.extend(list2);list3=list1
If u dont want to alter then try this:
list1 = [1,2]
list2 = [3,4]
list3=list1;list3.extend(list2)
And also:
myList=[1]
newList=myList;newList.append(2)
The append function modifies a list and returns None. Newlist was None because append() modifies the list directly, rather than returning the modified list.
This code will create the new list and add to it in one step.
myList = [1]
newList = myList + [2]