2013-10-29 3 views
3

저는 최근 특이한 문제에 직면 해 있습니다. 최근에 특정 유형의 목록 내포물을 만들 필요성을 느꼈습니다. 예를 들어목록 이해력이있는 다른 패턴

:

[ re.search('xyz', l).group(0) for l in my_list if re.search('xyz', l) ] 

이제 예리한 독자는이 목록의 이해가 정규 표현식 두 번 일치하는 않는 관찰 할 수있다.

나는이 '여분의'오버 헤드를 어떻게 든 목록 내재의 우아함을 잃어 버리는 것을 제거하고 싶습니다. 전에 누군가 그런 문제에 직면 했습니까? 그렇다면 어떻게 해결할 것인가? 나는 목록에서 값/객체 x에 적용하는 기능 f()이 일반적으로

은, 지금은 내 목록에 경우에만, f(x).a statisfies 어떤 조건을 f(x).b를 원하는.

empty_list = [] 
for x in my_list: 
    val = f(x) 
    if val.a == condition: 
     empty_list.append(val.b) 

이 가능한 솔루션입니다, 그러나 이것은 내가 더 '파이썬'방법이 있는지 해요, 너무 자세한 것 같다 :

나는

empty_list = [] 
for l in my_list: 
    match = re.search('xyz', l) 
    if match: 
     empty_list.append(match.group(0)) 

또는 더 일반적으로 알고 이렇게.

+0

"지능형리스트의 우아함을"- 당신이 여기에 초과 중량을 적용한 생각합니다. 표현식이 충분히 복잡 해지면 이해가 더 이상 "속할"수 없다 (그렇지 않으면 이해할 수 없을 것이다!) –

+2

중첩 된 목록 이해력을 사용할 수있다 : [[re.search ('에서 x에 대해 x.group (0) xyz ', l) for my_list] if x]' –

+0

@MartijnPieters 예, 그게 무슨 뜻인지, 미안 해요. 수정/수정. – ffledgling

답변

4

사용 발전기 함축하십시오이 있었는지 여부를 테스트하기위한

>>> [m.group(0) 
    for m in (re.search('xyz', item) for item in ['abc', 'aaxyz', 'xyz']) 
    if m is not None] 
['xyz', 'xyz'] 

: @tobias_k으로

# Your original list of data. 
my_list = [] 

# This 'knows' how to produce a new list of elements where each 
# element satisfies some test, here represented as `predicate`. 
# Looks like a list comprehension, but note the surrounding parens. 
passing = (x for x in my_list if predicate(x)) 

# This knows how to apply some function `f` to each element in the list. 
mapped = (f(x) for x in passing) 

# Now use the know-how above to actually create your list. 
# Note that because you're using chained generators, you are 
# only iterating over the original list once! 
results = list(mapped) 

# Or if you don't need all the intermediate values at once... 
for el in mapped: 
    do_something_with(el) 
3

코멘트, 당신은 중첩 된 이해 (여기 생성기)를 사용할 수 있다고 말했다 일치, 나는 항상 if m보다는 if m is not None를 사용합니다. 실패한 일치는 항상 None (신원 검사는 정말 빠름)이며, 진실에 대한 실제 일치 개체를 테스트하는 것은 일치 개체에 대한 메서드를 호출합니다.이 메서드는 충분한 수의 일치 개체에 대해 런타임에 중요한 영향을 미칠 수 있습니다. MB에서 GBs 범위의 입력 텍스트 크기 문제는 100 대가 아니지만 작은 규모의 문제에는 영향을주지 않습니다.

1

두 번 계산하지 않으려면 정규 표현식을 중간 생성자 이해도에 포함시킬 수 있습니다.이 지금부터

for l in my_list: 
    for match in [re.search('xyz', l)]: 
    if match: 
     empty_list.append(match.group(0)) 

:

의 우리는 인위적 한 요소 목록 내에서 경기를 넣어 더블 루프로 그것을 켤 수 있습니다

for l in my_list: 
    match = re.search('xyz', l) 
    if match: 
    empty_list.append(match.group(0)) 

당신을위한 루프 솔루션을 시작하자 for 루프와 if 문을 스택하면 중첩 목록 이해로 변환하는 것은 간단합니다.

[ match.group(0) for match in [re.search('xyz', l) for l in my_list] if match ] 

그리고 당신이 마지막 부분은 귀하의 질문에 관련이없는 불필요한 목록

[ match.group(0) for match in (re.search('xyz', l) for l in my_list) if match ] 

가 발생하지 않도록하려면 사실, 당신은 발전기 이해에 내부 목록을 만들 수 있습니다,하지만 난에 원 일부 언어에서는 이름을 목록 이해의 내부에 바인딩 할 수 있으므로 전체 내용을 중첩되지 않은 목록 이해로 작성할 수 있습니다. 다음은 유효한 파이썬 코드는 아니지만 유효한 코드가

[ group 0 match | elem <- myList, let match = reSearch "xyz" elem, match ] 

(나는 모든 만들어 사실을 모듈로 쓸 수 하스켈 예를 들어

[ match.group(0) for l in my list, let match = re.search('xyz', l), if match ] 

, 수 함수 이름).

+0

두 번째 비트'let match = re.search ('xyz', l)'는 내가 생각한 구문의 일종입니다. 유익한 너겟 덕분입니다. – ffledgling

+0

@ffledgling 문제 없습니다. –

1

개인적으로,이 경우에, 난 그냥 이런 짓을 했을까 :

matches = [i.group(0) for i in filter(None, (re.search('xyz', i) for i in my_list))] 

을합니다 (list없이 그냥 반복해야하는 경우).

filter은 부울 값이 True 인 생성자 식의 모든 요소를 ​​생성합니다 (이 경우 None이 아닌 것). 이 접근 방식 None 명시 적으로 확인하기를 원한다면

그러나, 당신은 다음과 같이해야합니다 :

matches = [i.group(0) for i in filter(lambda x: x is not None, (re.search('xyz', i) for i in my_list)))] 
+0

*지도 *. *필터*. 나는 이것을 왜 사용하지 않을 것이라고 생각 했는가? +1 나를 생각 나게하기 위해! – ffledgling

+0

@ffledgling 환영합니다. – rlms