2017-09-25 1 views
0

나는 이해력에 대한 기본적인 질문이 있습니다. 값 목록입니다 dicts의 목록이있다, 그것은 다음과 같습니다 : 내가 필요로하는 모든 고유 동물 목록 유형 값에서 얻을 수 있습니다사전 목록 처리 - 가독성 및 복잡성

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

I, 대한 하나, * 단 하나 강론 *에 매혹되지 않는다, 때때로 그들은 이해된다, 때때로 그렇지 않다.가독성을 고려해야합니다. 내일 이해 할거야? – wwii

+0

시간을내어 [ask]를 읽으십시오. – 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'}