2009-12-31 58 views
5

我有一個網格(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」方式?

回答

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的行)。然後執行整個操作,我轉移網格,刪除空行(原始數據中的列),再次轉置,然後刪除空白行。

如果只帶,其值爲false無,而不是其他的東西是非常重要的,在removeBlankRows功能更改爲:

def removeBlankRows(grid): 
    return [list(row) for row in grid if any(x is not None for x in row)] 
+0

謝謝!這是完美的。 – Matt

+0

如果應該將與「」或「[]」相似的值與「無」區分開來,則會出現錯誤。它也只比我的答案慢了一倍,比我的答案慢了26.8:12.3(當在兩者中都使用相同形式的any()時,顯然'任何(n不是x的n)'比'any (x)的')。 – 2009-12-31 05:00:39

+0

是的,我知道這不會是最快的方法,但是如果它更容易理解並且它不是關鍵循環的一部分,我認爲較慢的解決方案是可以接受的。 –

0

如果只有你有一個轉置功能,你可以這樣做:轉置(removeRows(轉(removeRows(MAT))))

其實...使用位掩碼是一個更好的主意。

讓我想想...

首先計算gridmask:

grid_mask = [ 
10000, 
00000, 
00000, 
00010, 
00000 
] 

現在除去零:

grid_mask = [ 
10000, 
00010, 
] 

現在,所有數據按位:

grid_mask = 10010 

現在刪除所有,但第一和第四列。

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) 
1

使用zip()移調衣衫襤褸的數組,再次運行清除程序,然後再zip()它。

+3

請添加細節。 –

+0

@Ipthnc:「添加詳細信息」==「編寫代碼」,這是程序員希望能夠做到的。 –

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]] 
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) 
] 
相關問題