python: copying list and appending in one step - list

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]

Related

how to get the list of the lists?

I have a problem like that:
list = ['a1',['b1',2],['c1',2,3],['d1',2,3,4]]
I want to get a new list like that
new_list['a1','b1','c1','d1']
I do like this:
lst = ['a1',['b1',2],['c1',2,3],['d1',2,3,4]]
for item in lst:
print(item)
result is:
a1
['b1', 2]
['c1', 2, 3]
['d1', 2, 3, 4]
But I want the first element of each result
The best answer is like this :
my_list = list()
lst = ['a1',['b1',2],['c1',2,3],['d1',2,3,4]]
for element in lst:
if type(element)==type('string'):
my_list.append(element)
else:
my_list.append(element[0])
print(my_list)
Thank you!
Do it as below:
>>> my_list = list()
>>> lst = ['a1',['b1',2],['c1',2,3],['d1',2,3,4]]
>>> for element in lst:
if type(element)==type('string'):
my_list.append(element)
else:
my_list.append(element[0])
It will produce:
>>> my_list
['a1', 'b1', 'c1', 'd1']
>>>
As you see above, first I created a list (named my_list) and then checked each elements of your list. If the element was a string, I added it to my_list and otherwise (i.e. it is a list) I added the first element of it to my_list.
I would do
res = []
for x in the_list:
if x is Array:
res.append(x[0])
else:
res.append(x)

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 3.4: adding value to list if condition exists

i have a scenario like this one:
mainList = [[9,5],[17,3],[23,1],[9,2]]
secondaryList = [9,12,28,23,1,6,95]
myNewList = []
myNewList.append([[a,b] for a,b in mainList if a in secondaryList])
this, return me to me:
myNewList = [[9,5],[23,1],[9,2]]
but I need only the first occourance of "a". In other words I need to obtain:
myNewList = [[9,5],[23,1]]
How can I achieve this?
First of all:
myNewList = []
myNewList.append([[a,b] for a,b in mainList if a in secondaryList])
simply is the same as
myNewList = [[a,b] for a,b in mainList if a in secondaryList]
Then:
What you're building is functionally a python dictionary. Your two-element lists in mainList are the same as dict.items()!
So what you'd do is build a dict out of mainList (reversing it, because usually, you'd just save the last, not the first occurence):
mainDict = dict([reversed(mainList)])
Then you just make your new list:
myNewList = [ (key, mainDict[key]) for key in secondaryList ]
You can use a set to store the first elements and then check for existing the first element before adding the sub-lists :
>>> seen=set()
>>> l=[]
>>> for i,j in mainList:
... if i in secondaryList and i not in seen:
... seen.add(i)
... l.append([i,j])
...
>>> l
[[9, 5], [23, 1]]
Or you can use collections.defaultdict and deque with specifying its maxlen.But note that you need to loop over your list from end to start if you want the first occourance of a because deque will keep the last insert value :
>>> from collections import defaultdict
>>> from functools import partial
>>> d=defaultdict(partial(deque, maxlen=1))
>>> for i,j in mainList[::-1]:
... if i in secondaryList:
... d[i].append(j)
...
>>> d
defaultdict(<functools.partial object at 0x7ff672706e68>, {9: deque([5], maxlen=1), 23: deque([1], maxlen=1)})

list in python behaviour

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.

How to get the difference between two lists?

I have two lists:
val list1 = List("word1","word2","word2","word3","word1")
val list2 = List("word1","word4")
I want to remove all occurrences of list2 elements from list1, i.e. I want
List("word2","word2","word3") <= list1 *minus* list2
I did list1 diff list2
which gives me List("word2","word2","word3","word1") which is removing only the first occurrence of "word1".
I cannot convert it to sets because I need knowledge about duplicates (see "word2" above). What to do?
You can use
val unwanted = list2.toSet
list1.filterNot(unwanted)
to remove all items in list2 (you don't need knowledge of duplicates in list2).
val list1 = List("word1","word2","word2","word3","word1")
val list2 = List("word1","word4")
list1 diff list2
This will do it.
You could try this:
val list1 = List("word1","word2","word2","word3","word1")
val list2 = List("word1","word4")
println(list1.filterNot(list2.contains(_)))