[英]Python - removing empty rows or columns in a list of lists
我想这个问题有两个部分:
我想避免使用 pandas 并且我确信有一些涉及列表理解的解决方案。 您可以假设列表的列表是矩形的。
例子:
鉴于:
lol = [['a',None,'c'],[None,None,None],['g',None,'i'],['j',None,None]]
(编辑 - 写“无”而不是无)
返回:
lol = [['a','c'],['g','i'],['j',None]]
也许您可以尝试这种简单的方法:
outs = []
for l in lol:
tmp = []
for x in l:
if x: # OR if x is not None: !<--- as comment suggested.
tmp.append(x)
if tmp: # skip empty list: 2nd one
outs.append(tmp)
print(outs)
[['a', 'c'], ['g', 'i'], ['j', 'None']]
matrix = [['a', 'b', 'c', '0'],
['0', 'None', 'x', 'y'],
['k', 'l', None, None],
[0, '', '', 'x']]
def remove_empty(matrix):
outs = []
for l in matrix:
tmp = []
for x in l:
if x:
tmp.append(x)
if tmp: # skip empty list: 2nd one
outs.append(tmp)
return outs
print(remove_empty(matrix))
= Outputs:
[['a', 'b', 'c', '0'], ['0', 'None', 'x', 'y'], ['k', 'l'], ['x']]
使用列表理解应该有效
step1 : 在每个索引 position 处计算 None 元素
step2 :一旦元素被计数,如果在某个索引处,None 计数元素的数量等于 lol 的长度,我们将消除这些元素
from collections import Counter
# note I have change the last element of the last sub to None and not 'None'
lol = [['a',None,'c'],[None,None,None],['g',None,'i'],['j',None, None]]
# here we count None step 1
missing_vals = Counter()
for sub in lol:
vals = {ind: int(not bool(val)) for ind, val in enumerate(sub)}
counter = Counter(vals)
missing_vals = missing_vals + counter
# step 2
out = [[a for val, a in enumerate(sub_list) if missing_vals[val] != len(lol)]
for sub_list in lol if any(sub_list)]
print(out)
[['a', 'c'], ['g', 'i'], ['j', None]]
您的示例 output 似乎与您在问题中所说的不匹配,所以我在这里做了一些更改。
my_list = [['a', None, 'c'], [None, None, None], ['g', None, 'i'], ['j', None, 'None']]
output_check = [['a', 'c'], ['g', 'i'], ['j', 'None']]
new_list = [[x, z] for x, y, z in my_list if x]
assert output_check == new_list
print(new_list)
>>> [['a', 'c'], ['g', 'i'], ['j', 'None']]
感谢 Prayson W. Daniel首先将此方法作为评论提交。
可能不是一个非常有效的答案,但我能想到的最好的答案,因为我认为不可能使用列表理解
for item in lol:
for i in range(item.count(None)): item.remove(None)
for i in range(lol.count([])): lol.remove([])
listcomp 方法怎么样:
[x for x in [[y for y in z if y is not None] for z in lol] if len (x) > 0]
我不推荐这个,因为它不是真的可读。
如果您的列表不包含任何值,除了None
评估为 false 您可以使用(感谢 Lucas M. Uriarte):
[[y for y in z if y is not None] for z in lol if any(z) ]
首先删除空行:
result = [row for row in lol if not all(a is None for a in row)]
交换行和列:
transpose = [list(i) for i in zip(*result)]
其次删除所有空列(转置列表中的行):
transpose= [row for row in transpose if not all(a is None for a in row)]
最后交换列/行:
result = [list(i) for i in zip(*transpose)]
这个可以清理你的列表,不管它有多嵌套
def clean_list(data):
cleaned_list = []
for obj in data:
if type(obj) == list:
sublist = clean_list(obj)
if sublist:
cleaned_list.append(sublist)
elif obj is not None:
cleaned_list.append(obj)
return cleaned_list
这是最有效的解决方案 - 实际上做你想做的 - 我可以想出:
def removeEmpties(lol):
colsCnt = len(lol[0])
emptyRow = [None]*colsCnt
# first remove all rows containing only None elements
lol2 = list(lst for lst in lol if lst!=emptyRow)
# second go through by columm
for col in range(colsCnt-1,-1,-1):
# and now look at that column in every row
for row in lol2:
# if an element in the current row is not None in that column
if row[col] is not None:
# we do not need to look any further,
# since this column has to remain
break;
else:
# if we could not find any non-None element,
# this column must be removed from all rows.
for row in lol2:
del row[col]
return lol2
print(removeEmpties([['a' ,None,'c' ],
[None,None,None],
['g' ,None,'i' ],
['j' ,None,None]]))
print(removeEmpties([['a' ,None,'c' ],
[None,None,None],
['g' ,None,'i' ],
['j' ,None,'None']]))
上述代码的output为:
[['a', 'c'], ['g', 'i'], ['j', None]]
[['a', 'c'], ['g', 'i'], ['j', 'None']]
您可以在https://onlinegdb.com/g76VzPGfo看到它的实际应用
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.