I have the following list:
a = [[['trial1', 'trial2'], 4], [[], 2]]
and I want to remove the list that have inside an empty list.So the following result:
c = [[['trial1', 'trial2'], 4]]
I am using the following code:
c = []
for b in a:
temp =[x for x in b if x]
if len(temp)>1:
c.append(temp)
It works ok, but it seems not to be a 'good way' of doing this task. Is there a more elegant way?
c = [l for l in a if [] not in l]
Use a list comprehension:
c = [x for x in a if [] not in x]
You could use list comprehension and all function to check whether everything in the list evaluted to the True:
c = [i for i in a if all(i)]
print(c)
[[['trial1', 'trial2'], 4]]
You may use filter built-in function.
a = [[['trial1', 'trial2'], 4], [[], 2]]
assert filter(lambda o: [] not in o, a) == [[['trial1', 'trial2'], 4]]
Since in Python 3 filter is lazy, you may need explicit conversion to list.
assert list(filter(lambda o: [] not in o, a)) == [[['trial1', 'trial2'], 4]]
Related
I have two lists like this:
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
I would now like to filter list a, to keep only the items which contain the items in list b. So the desired output would look like this:
[[1,2,3],[2,3,4]]
I have tried some nested list comprehensions, which I could think of, but could not get the desired output. Any advice is appreciated.
you could try something like this :
print([i for i in a if any(map(i.__contains__,b))])
>>> [[1, 2, 3], [2, 3, 4]]
I would try something like this:
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
result = [lst for lst in a if any(x in lst for x in b)]
A combination of list comprehension and sets would yield the wanted result. Note; I assume that repeated items and ordering is not of interest, if this is the case - a set won't work since it ignores ordering and only allows unique items.
A simple list comprehension would do, like below
filter_items = set(filter_items)
[sublist for sublist in original_list if not set(sublist).isdisjoint(filter_items)]
There's mainly one interesting part of this list comprehension, namely the if not set(sublist).isdisjoint(filter_items). Here you only keep the sublist if the set of sublist is not disjoint of the set filter_items i.e. none of the filter_items is in the sublist.
for your given example the provided answer would yield the following:
>>> a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
>>> b = set([1,2])
>>> [sublist for sublist in a if not set(sublist).isdisjoint(b)]
[[1, 2, 3], [2, 3, 4]]
Using a set approach the in can be mimic with an intersection:
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
b_as_set = set(b)
out = [l for l in a if b_as_set.intersection(l)]
# [[1, 2, 3], [2, 3, 4]]
I would try something like this.
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
print([lst for lst in a if any([item in b for item in lst])])
I have a nested list:
regions = [[1,2,3],[3,4],[1,3,4],[1,2,3,5]]
I want to remove every list in this nested list which is contained in another one, i.e., [3,4] contained in [1,3,4] and [1,2,3] contained in [1,2,3,5], so the result is:
result = [[1,3,4],[1,2,3,5]]
So far I'm doing:
regions_remove = []
for i,reg_i in enumerate(regions):
for j,reg_j in enumerate(regions):
if j != i and list(set(reg_i)-set(reg_j)) == []:
regions_remove.append(reg_i)
regions = [list(item) for item in set(tuple(row) for row in regions) -
set(tuple(row) for row in regions_remove)]
And I've got: regions = [[1, 2, 3, 5], [1, 3, 4]] and this is a solution, but I'd like to know what's the most pythonic solution?
(sorry for not posting my entire code before, I'm a new to this...
Here is a solution with list comprehension and all() function :
nested_list = [[1,2,3],[3,4],[1,3,4],[1,2,3,5],[2,5]]
result = list(nested_list) #makes a copy of the initial list
for l1 in nested_list: #list in nested_list
rest = list(result) #makes a copy of the current result list
rest.remove(l1) #the list l1 will be compared to every other list (so except itself)
for l2 in rest: #list to compare
if all([elt in l2 for elt in l1]): result.remove(l1)
#if all the elements of l1 are in l2 (then all() gives True), it is removed
returns:
[[1, 3, 4], [1, 2, 3, 5]]
Further help
all() built-in function: https://docs.python.org/2/library/functions.html#all
copy a list: https://docs.python.org/2/library/functions.html#func-list
list comprehension: https://www.pythonforbeginners.com/basics/list-comprehensions-in-python
I'm definitely overlooking a simpler route, but this approach works
list comprehension
from itertools import product
l = [[1,2,3],[3,4],[1,3,4],[1,2,3,5]]
bad = [i for i in l for j in l if i != j if tuple(i) in product(j, repeat = len(i))]
final = [i for i in l if i not in bad]
Expanded explanation
from itertools import product
l = [[1,2,3],[3,4],[1,3,4],[1,2,3,5]]
bad = []
for i in l:
for j in l:
if i != j:
if tuple(i) in product(j, repeat = len(i)):
bad.append(i)
final = [i for i in l if i not in bad]
print(final)
[[1, 3, 4], [1, 2, 3, 5]]
Basically, I'm trying to do remove any lists that begin with the same value. For example, two of the below begin with the number 1:
a = [[1,2],[1,0],[2,4],[3,5]]
Because the value 1 exists at the start of two of the lists -- I need to remove both so that the new list becomes:
b = [[2,4],[3,5]]
How can I do this?
I've tried the below, but the output is: [[1, 2], [2, 4], [3, 5]]
def unique_by_first_n(n, coll):
seen = set()
for item in coll:
compare = tuple(item[:n])
print compare # Keep only the first `n` elements in the set
if compare not in seen:
seen.add(compare)
yield item
a = [[1,2],[1,0],[2,4],[3,5]]
filtered_list = list(unique_by_first_n(1, a))
An efficient solution would be to create a Counter object to hold the occurrences of the first elements, and then filter the sub-lists in the main list:
from collections import Counter
counts = Counter(l[0] for l in a)
filtered = [l for l in a if counts[l[0]] == 1]
#[[2, 4], [3, 5]]
If you are happy to use a 3rd party library, you can use Pandas:
import pandas as pd
a = [[1,2],[1,0],[2,4],[3,5]]
df = pd.DataFrame(a)
b = df.drop_duplicates(subset=[0], keep=False).values.tolist()
print(b)
[[2, 4], [3, 5]]
The trick is the keep=False argument, described in the docs for pd.DataFrame.drop_duplicates.
You can use collections.Counter with list comprehension to get sublists whose first item appears only once:
from collections import Counter
c = Counter(n for n, _ in a)
b = [[x, y] for x, y in a if c[x] == 1]
Solution 1
a = [[1,2],[1,0],[2,4],[3,5]]
b = []
for item in a:
i = 0
if item[0] == a[i][0]:
i =+ 1
continue
else:
b.append(item)
i += 1
Solution 2
a = [[1,2],[1,0],[2,4],[3,5]]
b = []
for item in a:
for i in range(0, len(a)):
if item[0] == a[i][0]:
break
else:
if item in b:
continue
else:
b.append(item)
Output
(xenial)vash#localhost:~/pcc/10$ python3 remove_help.py
[[1, 2], [1, 0], [2, 4], [3, 5]]
[[2, 4], [3, 5]]
Achieved your goal no complex methods involed!
Enjoy!
I have a nested list and in every list the first item is a string that ends with .abc. I would like to remove all the .abc characters from my nested list.
Here's what I have got:
x = [['car.abc', 1, 2], ['ship.abc', 3, 4]]
And I would like to my nested list to be the following:
x = [['car', 1, 2], ['ship', 3, 4]]
How can I achieve this?
Using a simple for loop.
x = [['car.abc', 1, 2], ['ship.abc', 3, 4]]
for i in x:
i[0] = i[0].rsplit(".", 1)[0]
print(x)
Using nested regular expressions and list comprehension:
>>> import re
>>> [[re.sub(r'.abc$', '', e) if isinstance(e, basestring) else e for e in l] for l in x]
[['car', 1, 2], ['ship', 3, 4]]
isinstance(e, basestring) checks whether e is a string (see this question).
For a string e, re.sub(r'.abc$', '', e) replaces the part you specified
Otherwise e is untouched
The preceding happens for any element e in a list l, for each l in x.
Check online demo
x = [['car.abc', 1, 2], ['ship.abc', 3, 4]]
new_x=[]
for lst in x:
temp_lst=[]
for item in lst:
if(str(item)[-4:] == '.abc'):
item = str(item)[:-4]
temp_lst.append(item)
new_x.append(temp_lst)
print(new_x)
The following is the first line from my list l:
[0.0, 753.128, 990.43, 686.832, 366.922, -93.454, 1.0]
This is the result of:
print l[0]
I want to take all the first element from all such *lines of my list and assign them to another list. How can I do it in python?
Using a list comprehension:
lists = [[1,2,3], [4,5,6]]
[ l[0] for l in lists ]
That would do it. Nicer is to use map: you map a list of lists to a list of their heads:
map( lambda l: l[0], lists )
If performance is important, you may want to create an iterator over the heads of your lists:
heads = itertools.imap( lambda l: l[0], enumerate(lists))
for head in heads:
print head
Basic list comprehension:
another_list = [sublist[0] for sublist in l]
Try this:
a = [[1,2,3], ['a','b','c'], [True, False]]
first_elements = [e[0] for e in a]
print first_elements
>>> [1, 'a', True]
Something like this?
>>> a = [1, 2, 3, 4]
>>> b = [5,6,7,8]
>>> ab = [a, b]
>>> map (lambda x : x[0], ab)
[1, 5]
newlist=[]
for l in lst:
newlist.append(l[0])