2017-09-25 43 views
0

我有關於理解的基本問題。 有類型的字典,其中值是列表的列表,它看起來像這樣:字典處理列表 - 可讀性和複雜性

listionary = [{'path': ['/tmp/folder/cat/number/letter', '/tmp/folder/hog/char/number/letter', '/tmp/folder/hog/number/letter', '/etc'], 
'mask': True, 
'name': 'dict-1'}, 
{'path': ['/tmp/folder/dog/number-2/letter-4', '/tmp/folder/hog-00/char/number-1/letter-5', '/tmp/folder/cow/number-2/letter-3'], 
'mask': True, 
'name': 'dict-2'}, 
{'path': ['/tmp/folder/dog_111/number/letter', '/tmp/folder/ant/char/number/letter', '/tmp/folder/hen/number/letter'], 
'mask': True, 
'name': 'dict-3'}] 

我需要的是從列表類型的值,讓每一個獨特的動物。 動物總是在tmp /文件夾/和下一個/之間。 我所做的:

import re 
flat_list = [item for sublist in [i['path'] for i in listionary] for item in sublist] 
animals = list(set([re.search('folder/([a-z]+)', elem).group(1) for elem in flat_list if 'tmp' in elem])) 

它可能也壓縮成一條線,但它是相當複雜的,不可讀:

animals = list(set([re.search('folder/([a-z]+)', elem).group(1) for elem in [item for sublist in [i['path'] for i in listionary] for item in sublist] if 'tmp' in elem])) 

有什麼金科玉律(如蟒蛇的禪宗)關於大小理解? 我該如何做得更好?先謝謝你。

+2

我,對一個,我不迷戀*單行者*,有時他們有道理,有時他們沒有。可讀性應該是一個考慮因素。你明天會明白嗎? – wwii

+0

請花時間閱讀[問]。 – wwii

+0

的理解受制於79或119(根據偏好)列指南相同,如果你超過這個指標,我會考慮拆分它。 – Aaron

回答

1

我怎樣才能使它更好?

  1. 有其他人閱讀它。 ✓
  2. 使用的功能封裝更復雜的操作
  3. 不循環嵌套在同一行

這是我怎麼會打破過去的兩個點..

def get_animals(d): 
    animals = [] 
    for item in d['path']: 
     if item.startswith('/tmp/folder/'): 
      animals.append(item[12:item.find('/',12)]) 
    return animals 

animals = set() 
for d in dlist: 
    animals.update(get_animals(d)) 
animals = list(animals)
0

你可以試試這個:

listionary = [{'path': ['/tmp/folder/cat/number/letter', '/tmp/folder/hog/char/number/letter', '/tmp/folder/hog/number/letter', '/etc'], 
'mask': True, 
'name': 'dict-1'}, 
{'path': ['/tmp/folder/dog/number-2/letter-4', '/tmp/folder/hog-00/char/number-1/letter-5', '/tmp/folder/cow/number-2/letter-3'], 
'mask': True, 
'name': 'dict-2'}, 
{'path': ['/tmp/folder/dog_111/number/letter', '/tmp/folder/ant/char/number/letter', '/tmp/folder/hen/number/letter'], 
'mask': True, 
'name': 'dict-3'}] 
import re 
from itertools import chain 
animals = list(set(chain.from_iterable([[re.findall("/tmp/folder/(.*?)/", b)[0] for b in i["path"] if re.findall("/tmp/folder/(.*?)/", b)] for i in listionary]))) 

輸出:

['hog', 'hog-00', 'cow', 'dog_111', 'dog', 'cat', 'ant', 'hen'] 
0

您可以通過添加新行和縮進它更具可讀性。我停在item for sublist...這條線上,因爲我不明白代碼邏輯,但大概你可以在那裏添加更多的換行符。

animals = list(
    set([ 
      re.search('folder/([a-z]+)', elem).group(1) for elem in [ 
       item for sublist in [i['path'] for i in listionary] for item in sublist 
      ] 
      if 'tmp' in elem 
    ]) 
) 

這就是說,我會考慮這樣的事情是更可讀:

這裏應用經驗
def animal_name_from_path(path): 
    return re.search('folder/([a-z]+)', path).group(1) 

def is_animal_path(path): 
    return '/tmp' in path 

def deduplicate(L): 
    return list(set(L)) 

path_list = [] 
for item in listionary: 
    path_list.extend(item['path']) 

animals = deduplicate([animal_name_from_path(path) for path in path_list if is_animal_path(path)]) 

一個規則是,任何概念應該有個名字。在您的原始代碼中,item for sublist in [i['path'] for i in listionary] for item in sublist很難理解,因爲它不清楚itemi應該是什麼。在這個新的塊中,更清晰的是,你只是展開一系列路徑。一旦所有概念被命名,動物名稱識別碼就更容易理解。在這裏,我可能已經把它變得極端 - 你可以找到你自己的快樂平衡,你發現最可讀的。

0

縮短解決方案:

animals = set(re.search(r'/folder/([a-z]+)', p).group(1) for d in listionary for p in d['path'] if '/tmp' in p) 
print(animals) 

輸出:

{'hog', 'cat', 'dog', 'cow', 'hen', 'ant'}