我有一个网格(6行,5列):
grid = [
[None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None],
]
我增加了网格,它可能会变成:
grid = [
[{"some" : "thing"}, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, {"something" : "else"}, None],
[None, {"another" : "thing"}, None, None, None],
[None, None, None, None, None],
]
我想删除其中包含所有 None
的整个行和列。所以在前面的代码中,网格将转换为:
grid = [
[{"some" : "thing"}, None, None],
[None, None, {"something" : "else"}],
[None, {"another" : "thing"}, None],
]
我删除了第1,2,5行(零索引)和第2列和第4列。
我现在删除行的方式:
for row in range(6):
if grid[row] == [None, None, None, None, None]:
del grid[row]
我还没有很好的方法来删除None
列。这样做有“pythonic”的方法吗?
答案 0 :(得分:7)
这不是最快的方式,但我认为这很容易理解:
def transpose(grid):
return zip(*grid)
def removeBlankRows(grid):
return [list(row) for row in grid if any(row)]
print removeBlankRows(transpose(removeBlankRows(transpose(grid))))
输出:
[[{'some': 'thing'}, None, None],
[None, None, {'something': 'else'}],
[None, {'another': 'thing'}, None]]
工作原理:我使用zip
编写一个转换行和列的函数。第二个函数removeBlankRows
删除所有元素都为None的行(或在布尔上下文中计算为false的任何元素)。然后执行整个操作我转置网格,删除空白行(这是原始数据中的列),再次转置,然后删除空行。
如果仅删除None而不是其他评估为false的内容很重要,请将removeBlankRows函数更改为:
def removeBlankRows(grid):
return [list(row) for row in grid if any(x is not None for x in row)]
答案 1 :(得分:1)
grid = ...
# remove empty rows
grid = [x for x in grid if any(x)]
# if any value you put in won't evaluate to False
# e.g. an empty string or empty list wouldn't work here
# in that case, use:
grid = [x for x in grid if any(n is not None for n in x)]
# remove empty columns
if not grid:
raise ValueError("empty grid")
# or whatever, as next line assumes grid[0] exists
empties = range(len(grid[0])) # assume all empty at first
for r in grid:
empties = [c for c in empties if r[c] is None] # strip out non-empty
if empties:
empties.reverse() # apply in reversed order
for r in grid:
for c in empties:
r.pop(c)
答案 2 :(得分:1)
使用zip()
转置不规则阵列,再次运行清除例程,然后再次zip()
。
答案 3 :(得分:0)
如果你只有转置功能,你可以这样做:transpose(removeRows(transpose(removeRows(mat))))
实际上......使用位掩码是一个更好的主意。
让我考虑一下......
首先计算网格掩码:
grid_mask = [
10000,
00000,
00000,
00010,
00000
]
现在删除零:
grid_mask = [
10000,
00010,
]
现在和所有值按位:
grid_mask = 10010
现在删除除第1和第4列以外的所有列。
答案 4 :(得分:0)
这是快速尝试
它适用于任何大小的矩阵,行也可以是不同的大小,并且可能很快:)
from collections import defaultdict
grid = [
[{"some" : "thing"}, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, {"something" : "else"}, None],
[None, {"another" : "thing"}, None, None, None],
[None, None, None, None, None],
]
# go thru the grid remove, rows which have all None
# doing that count None in each columns, remove such columns later
newGrid = []
colSize = len(grid)
colCount = defaultdict(int)
for row in grid:
allNone = True
for c, cell in enumerate(row):
if cell is None:
colCount[c] += 1
else:
allNone = False
if not allNone: # only add rows which are not all none
newGrid.append(row)
# get cols which need to be removed
removeCols = [col for col, count in colCount.iteritems() if count == colSize]
removeCols.sort(reverse=True)
# now go thru each column and remove all None Columns
for row in newGrid:
for col in removeCols:
row.pop(col)
grid = newGrid
import pprint
pprint.pprint(grid)
<强>输出:强>
[[{'some': 'thing'}, None, None],
[None, None, {'something': 'else'}],
[None, {'another': 'thing'}, None]]
答案 5 :(得分:0)
您还可以使用内置函数any()
,它检查迭代的任何元素是否具有非None
值。它比比较快,你不需要知道迭代的大小。
>>> def remove_rows( matrix ):
... '''Returns a matrix without empty rows'''
... ret_matrix = []
... for row in matrix:
... #Check if the row has any value or all are None
... if any(row):
... ret_matrix.append(row)
...
... return ret_matrix
#You can do it also with a list comprehension, which will be even faster
>>> def remove_rows(matrix):
... '''Returns a matrix without empty rows'''
... ret_matrix = [ row for row in matrix if any(row) ]
... return ret_matrix
>>> grid = [
... [{"some" : "thing"}, None, None, None, None],
... [None, None, None, None, None],
... [None, None, None, None, None],
... [None, None, None, {"something" : "else"}, None],
... [None, {"another" : "thing"}, None, None, None],
... [None, None, None, None, None],
... ]
>>> grid = remove_rows( grid )
>>> grid
[
[{'some': 'thing'}, None, None, None, None],
[None, None, None, {'something': 'else'}, None],
[None, {'another': 'thing'}, None, None, None]
]
#transpose grid using zip (using asterisk)
>>> grid = zip(*grid)
#Note that zip returns tuples
>>> grid
[
({'some': 'thing'}, None, None),
(None, None, {'another': 'thing'}),
(None, None, None),
(None, {'something': 'else'}, None),
(None, None, None)
]
>>> grid = remove_rows(grid)
>>> grid
[
({'some': 'thing'}, None, None),
(None, None, {'another': 'thing'}),
(None, {'something': 'else'}, None)
]
>>> #Transpose again to get the first matrix, without empty rows or columns
>>> final_grid = zip(*grid)
>>> final_grid
[
({'some': 'thing'}, None, None),
(None, None, {'something': 'else'}),
(None, {'another': 'thing'}, None)
]