2013-10-03 117 views
1

空元素我有這樣剝離從列表

dl= [{'plat': 'unix', 'val':['', '', '1ju', '', '', '202', '', '']}, 
    {'plat': 'Ios', 'val':['', '', '', '', 'Ty', '', 'Jk', '']}, 
    {'plat': 'NT',  'val':['', '', 1,  '', '' , '202', '', '']}, 
    {'plat': 'centOs', 'val':['', '', '', '', '', '202', '', '']}, 
    {'plat': 'ubuntu', 'val':['', 'KL', '1', '', '', '', '', '9i0']}] 
           ^   ^
           |    | 
           \    /
            Delete these 

一個Python數據結構,我想刪除列表中的'val'其中每個列表中的同一列中的值是空的位置。例如,列表中的位置0和3(dl)。我想獲得的輸出是這樣的:

Output= [{'plat': 'unix', 'val':['', '1ju', '', '202', '', '']}, 
     {'plat': 'Ios', 'val':['', '', 'Ty', '', 'Jk', '']}, 
     {'plat': 'NT',  'val':['', 1,  '' , '202', '', '']}, 
     {'plat': 'centOs', 'val':['', '', '', '202', '', '']}, 
     {'plat': 'ubuntu', 'val':['KL', '1', '', '', '', '9i0']}] 
+0

你想刪除所有的空元素? – Tyler

+0

試着讓示例更簡單。爲什麼你的代碼示例包含「plat」:'unix'?另外,我不清楚「位置0和3在列表(dl)」中的含義:在輸出列表中,您更改了所有位置。 –

+1

刪除所有列表中的元素爲空的位置,如位置0在所有5個列表中都爲空('val') –

回答

3

讓我們做這兩個步驟。首先,找到索引刪除:

lists = [e['val'] for e in dl] 
idx_to_remove = [i for i, elem in enumerate(map(any, zip(*lists))) if not elem] 

其次,讓我們來過濾原始名單:

for l in lists: 
    l[:] = [elem for i, elem in enumerate(l) if i not in idx_to_remove] 

結果:

>>> pprint.pprint(dl) 
[{'plat': 'unix', 'val': ['', '1ju', '', '202', '', '']}, 
{'plat': 'Ios', 'val': ['', '', 'Ty', '', 'Jk', '']}, 
{'plat': 'NT', 'val': ['', 1, '', '202', '', '']}, 
{'plat': 'centOs', 'val': ['', '', '', '202', '', '']}, 
{'plat': 'ubuntu', 'val': ['KL', '1', '', '', '', '9i0']}] 
0
from itertools import izip 
from operator import itemgetter 

# create an iterator over columns 
columns = izip(*(d['val'] for d in dl)) 

# make function keeps non-empty columns 
keepfunc = itemgetter(*(i for i, c in enumerate(columns) if any(c))) 

# apply function to each list 
for d in dl: 
    d['val'] = list(keepfunc(d['val'])) 
2
dl= [{'plat': 'unix', 'val':['', '', '1ju', '', '', '202', '', '']}, 
    {'plat': 'Ios', 'val':['', '', '', '', 'Ty', '',  'Jk', '']}, 
    {'plat': 'NT',  'val':['', '', 1, '', '' , '202', '', '']}, 
    {'plat': 'centOs', 'val':['', '', '', '', '', '202', '', '']}, 
    {'plat': 'ubuntu', 'val':['', 'KL','1', '', '', '', '', '9i0']}] 

def empty_indices(lst): 
    return {i for i,v in enumerate(lst) if not v} 

# Need to special-case the first one to initialize the set of "emtpy" indices. 
remove_idx = empty_indices(dl[0]['val']) 
# Here we do the first one twice. We could use itertools.islice but it's 
# probably not worth the miniscule speedup. 
for item in dl: 
    remove_idx &= empty_indices(item['val']) 

for item in dl: 
    item['val'] = [k for i,k in enumerate(item['val']) if i not in remove_idx] 

# print the results. 
import pprint 
pprint.pprint(dl) 
+1

刪除'0'索引後,del item ['val'] [3]'實際上會刪除第5個元素,而不是第4個元素,因爲我們需要它。 –

+0

@RomanBodnarchuk - 謝謝。一定還是有點睡着了。無論如何,我不喜歡那部分。我已經將它改爲列表理解。當然,我想我們可以使用StevenRumvalski使用的迭代反向和流行解決方案 - 或者,我可以對remove_idx進行排序,使其降序...但list-comp更好。 – mgilson

+0

@mgilson:我不喜歡流行的解決方案,所以我改變了它。我也認爲我通過確定要保留的列而不是刪除列來使其更清潔。 –

0

另一種可能的解決方案(不是真的有效,但也... )。 zip()真的被低估...

# extract the values as a list of list 
vals = [item["val"] for item in dl] 
# transpose lines to columns 
cols = map(list, zip(*lines)) 
# filter out empty columns 
cols = [c for c in cols if filter(None, c)] 
# retranspose columns to lines 
lines = map(list, zip(*cols)) 
# build the new dict 
output = [ 
    dict(plat=item["plat"], val=line) for item, line in zip(dl, lines) 
    ]