I have a list of lists of tuples of integers.
ls = [[(a_1, a_2), (b_1, b_2)], [(c_1, c_2), (d_1, d_2), (e_1, e_2)], ...]
And I need to delete every item of ls that contains a tuple whose second entry is equal to a predetermined integer.
I tried this:
for item in ls:
for tpl in item:
if tpl[1] == m:
ls.remove(item)
But for some reason, this only removes a few of the list items but not all containing a tuple with second entry = m.
Use a list comprehension:
ls = [item for item in ls if all(tuple[1] != m for tuple in item)]
Or use a filter:
ls = filter(lambda item: all(tuple[1] != m for tuple in item),ls)
Code sucks and we need less of it - here's as sparse as it gets.
[l for l in ls if m not in [i[1] for i in l]]
The best way to filter a list in python is to use a list comprehension:
filtered = [item for item in ls if not(contains_m(item))]
And then all you need is a function that can tell if an item contains m, for example:
def contains_m(item):
return any([tpl[1] == m for tpl in item])
Removing an itme from list is not a good idea while iterating though it.
Try that (if where are talking Python here)
ls = [[('a_1', 'a_2'), ('b_1', 'b_2')], [('c_1', 'c_2'), ('d_1', 'd_2'), ('e_1', 'e_2')]]
m='c_2'
print [ x for x in ls if not [ y for y in x if y[1]==m ]]
Python's list iterator is lazy. This means that when you remove an item from the list, it will skip the next item. For example, say you want to remove all ones from the following list:
[1, 1, 2]
Your for loop starts at index 0:
[1, 1, 2]
^
It removes the element and moves on:
[1, 2]
^
This example is just to help illustrate the issue. One simple workaround is to loop backwards using the index:
for ind in range(len(ls)-1, -1, -1):
item = ls[ind]
for tpl in item:
if tpl[1] == m:
del ls[ind]
break # You can end the inner loop immediately in this case
Another way is to make a copy of the list to iterate over, but remove from the original:
for item in ls[:]:
for tpl in item:
if tpl[1] == m:
ls.remove(item)
break
The last approach can be simplified into creating an output list that contains only the elements that you want. This is easiest to do with a list comprehension. See #AlexeySmirnov 's answer for the best way to do that.
Related
I want to remove the empty string ('') in the list of list in python.
My input is
final_list=[['','','','',''],['','','','','',],['country','','','',''],['','','India','','']]
My expected output should be like :
final_list=[['country'],['India']]
I am new to python i just to tried this (Note* below tried code is not intended)
final=[]
for value in final_list:
if len(set(value))==1:
print(set(value))
if list(set(value))[0]=='':
continue
else:
final.append(value)
else:
(final.append(value)
print(final)
Can some one help on me achieve the expected output? in the generic way.
You can use a list comprehension to check if any values exist within the sub list, and a nested comprehension to only retrieve those that have a value
[[x for x in sub if x] for sub in final_list if any(sub)]
Try the below
final_list=[['','','','',''],['','','','','',],['country','','','',''],['','','India','','']]
lst = []
for e in final_list:
if any(e):
lst.append([x for x in e if x])
print(lst)
output
[['country'], ['India']]
You can use a nested list comprehension with any that checks if list contains at least one string not empty:
>>> [[j for j in i if j] for i in final_list if any(i)]
[['country'], ['India']]
Assuming the strings inside the list of list doesn't contain , then
outlist = [','.join(innerlist).split(',') for innerlist in final_list]
But if the strings in the list of list can contain , then
outlist = []
for inlist in final_list:
outlist.append(s for s in inlist if s != '')
You could do the following (Using my module sbNative -> python -m pip install sbNative)
from sbNative.runtimetools import safeIter
final_list=[['','','','',''],['','','','','',],['country','','','',''],['','','India','','']]
for sub_list in safeIter(final_list):
while '' in sub_list: ## removing empty strings from the sub list until there are no left
sub_list.remove('')
if len(sub_list) == 0: ## checking and removing lists in case they are empty
final_list.remove(sub_list)
print(final_list)
Use a list comprehension to find all sublists that contain any value. Then use a filter to get all entries in this sublist that contain a value (here checked with bool).
final_list = [list(filter(bool, sublist)) for sublist in final_list if any(sublist)]
For a list of lists ['"fo"', '"ba"', '1','2','ect.','"fo"', '"ba"','ect.','57','"trip"'] , what's the cleanest way to get all the indices for '"fo"' when '"fo"','"ba"' appear together in the list. in Python?
Similar to one edited for 1 item answered Dec 30'14 at 21:03 and Edited Jul 28 at 21:30 by MrWonderful
For a list ["foo", "bar", "baz"] and an item in the list "bar", what's the cleanest way to get its index (1) in Python?
If you're looking for '"fo"' immediately followed by '"ba"', something like
import itertools
l = ['"fo"', '"ba"', '1','2','ect.','"fo"', '"ba"','ect.','57','"trip"']
print([i for i, x in enumerate(zip(l, itertools.islice(l, 1, None))) if x == ('"fo"', '"ba"')])
This should do it:
for one_list in list_of_lists:
if ("fo" in one_list ) and ("ba" in one_list):
return indices = [i for i, x in enumerate(one_list) if x == "fo"]
You could try this! We iterate through the list once, checking if the index we are on and the next thing down match what you want. If it does, we add it to a list. We also check that we are not on the last index of the list to avoid indexOutOfBounds exceptions.
results = []
for i in range(0, len(lst)):
if i < len(lst)-1 and lst[i] == '"fo"' and lst[i+1] == '"ba"':
results.append(i)
return results
Note that this works for your example, which looks to be a single list rather than a list of lists. To apply to lists of lists, you could add an extra for loop iteration through each sublist.
This is what I ended up with. I adapted Patrick Haugh's answer.
import itertools # C-D create list of indices
r_va=('"EMD"', '"20170820"')
L = ([i for i, x in enumerate(zip(l, itertools.islice(l, 1, None))) if \
x == (r_va)])
e =(len(l))
L.append(e) # adds end length of no_spaces L is list of indexes of l
I have a Python list like:
['user#gmail.com', 'someone#hotmail.com'...]
And I want to extract only the strings after # into another list directly, such as:
mylist = ['gmail.com', 'hotmail.com'...]
Is it possible? split() doesn't seem to be working with lists.
This is my try:
for x in range(len(mylist)):
mylist[x].split("#",1)[1]
But it didn't give me a list of the output.
You're close, try these small tweaks:
Lists are iterables, which means its easier to use for-loops than you think:
for x in mylist:
#do something
Now, the thing you want to do is 1) split x at '#' and 2) add the result to another list.
#In order to add to another list you need to make another list
newlist = []
for x in mylist:
split_results = x.split('#')
# Now you have a tuple of the results of your split
# add the second item to the new list
newlist.append(split_results[1])
Once you understand that well, you can get fancy and use list comprehension:
newlist = [x.split('#')[1] for x in mylist]
That's my solution with nested for loops:
myl = ['user#gmail.com', 'someone#hotmail.com'...]
results = []
for element in myl:
for x in element:
if x == '#':
x = element.index('#')
results.append(element[x+1:])
i have this
lst = [['100','LA'],['101','NY'],['100','NC']]
lst2 = []
i need to check if there's any 100,101,etc repeated and remove the repeated numbers. So the second list would look like this
lst2=[['100','LA'],['101','NY']]
because the 100 was already added once in that second list
A quick and dirty way to do this is using a generic uniqueness filter:
def uniqueness(iterable,key=lambda x:x):
seen = set()
for item in iterable:
fitem = key(item)
if fitem not in seen:
yield item
seen.add(fitem)
You can then use it like:
list2 = list(uniqueness(lst,key=lambda x:x[0]))
If you do not specify, the filter will assume the entire element (but this will fail here, because list is not hashable).
An answer without lambda's.
nmbrs = [n for n, city in lst]
lst2 = [x for i, x in enumerate(lst) if x[0] not in nmbrs[:i]]
I have the next list of
testList = []
testList.append([0,-10])
testList.append([-12,122])
testList.append([13,172])
testList.append([17,296])
testList.append([-10,80])
testList.append([-16,230])
testList.append([-18, 296])
testList.append([-2, -8])
testList.append([-5,10])
testList.append([2,-4])
and another lists which contains elements from previous list:
m1 = []
m1.append([0, -10])
m1.append([13, 172])
Then I try to get a subarray from the list testList with the next statement:
[element for i, element in enumerate(testList) if i not in m1]
But I get the same list as testList.
How can I achieve this?
If you don't care about the order in the lists, you can use sets instead:
# result will be a set, not a list
not_in_testlist = set(testlist) - set(m1)
If you want the result to be a list again:
# result will be a list with a new order
not_in_m1 = list(set(testlist) - set(m1))
Be aware that using sets will lose the order of the original lists because sets are unordered types (they use hashing under the hood).
If you need to preserve the order, then Andrew Allaire's answer is correct:
# result is a list, order is preserved
not_in_testlist = [e for e in testlist if e not in m1]
The problem is with your use of enumerate. The i is just going to be an integer, and therefor never in a list that only has lists in it. Try this:
[element for element in testList if element not in m1]
Try with this:
def clean_list(my_list, exclusion_list):
new_list = []
for i in my_list:
if i in exclusion_list:
continue
else:
new_list.append(i)
return new_list