Find and delete list elements if matching a string - list

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)

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.

Unique elements inside lists of list

If I have a nested list like:
l = [['AB','BCD','TGH'], ['UTY','AB','WEQ'],['XZY','LIY']]
In this example, 'AB' is common to the first two nested lists. How can I remove 'AB' in both lists while keeping the other elements as is? In general how can I remove a element from every nested list that occurs in two or more nested lists so that each nested list is unique?
l = [['BCD','TGH'],['UTY','WEQ'],['XZY','LIY']]
Is it possible to do this with a for loop?
Thanks
from collections import Counter
from itertools import chain
counts = Counter(chain(*ls)) # find counts
result = [[e for e in l if counts[e] == 1] for l in ls] # take uniqs
One option is to do something like this:
from collections import Counter
counts = Counter([b for a in l for b in a])
for a in l:
for b in a:
if counts[b] > 1:
a.remove(b)
Edit: If you want to avoid the (awfully useful standard library) collections module (cf. the comment), you could replace counts above by the following custom counter:
counts = {}
for a in l:
for b in a:
if b in counts:
counts[b] += 1
else:
counts[b] = 1
A somewhat short solution without imports would be to create a reduced version of the original list first, then iterate through the original list and remove elements with counts greater than 1:
lst = lst = [['AB','BCD','TGH'], ['UTY','AB','WEQ'],['XZY','LIY']]
reduced_lst = [y for x in lst for y in x]
output_lst = []
for chunk in lst:
chunk_copy = chunk[:]
for elm in chunk:
if reduced_lst.count(elm)>1:
chunk_copy.remove(elm)
output_lst.append(chunk_copy)
print(output_lst)
Should print:
[['BCD', 'TGH'], ['UTY', 'WEQ'], ['XZY', 'LIY']]
I hope this proves useful.

create a list with a variable part

I would like to create a list with a variable part :
mylist = ['a1','a2','a3','a4','a5']
I am trying :
i = range(1,5)
ii = [str(x) for x in i]
which works, and then I would like to do :
mylist = list('a' + x for x in ii)
but that doesn't work
Ranges are half-open in Python so you must use xrange(1,6), and although concatenation is fine (between two strings) you could also use str.format. You can iterate over the numbers and append them to a in one go in a list comprehension with xrange ( see xrange vs range) such that you don't need to create two temporary lists in the process as you did:
>>> [str.format('a{0}', x) for x in xrange(1,6)]
['a1', 'a2', 'a3', 'a4', 'a5']
>>> ['a' + str(x) for x in xrange(1,6)]
['a1', 'a2', 'a3', 'a4', 'a5']

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)

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]