문제

목록의 각 항목이 파이썬의 문자열에있는 횟수를 얻으려고 노력하고 있습니다.

paragraph = "I eat bananas and a banana"

def tester(x): return len(re.findall(x,paragraph))

map(tester, ['banana', 'loganberry', 'passion fruit'])

반환 [2, 0, 0

그러나 내가하고 싶은 것은 단락 값을 map () 함수에 공급할 수 있도록 이것을 확장하는 것입니다. 현재 Tester () 함수는 단락을 하드 코딩했습니다. 누구 든지이 작업을 수행 할 방법이 있습니까 (아마도 단락 값의 N 길이 목록을 작성)? 여기에 다른 아이디어가 있습니까?

각 배열 값은 미래의 어느 시점에서 가중치를 가질 것이므로, 값을 모두 함께 구부리지 않고 목록에 값을 유지해야합니다.

업데이트 : 단락은 종종 20K이며 목록에는 종종 200 명 이상의 회원이 있습니다. 내 생각은 MAP가 동시에 작동한다는 것입니다. 따라서 일련의 방법보다 훨씬 효율적입니다.

도움이 되었습니까?

해결책

다음은 GoalPosts의 움직임에 대한 응답입니다 ( "가까운 미래에 단어 구분자가 필요하기 때문에 동정인이 필요할 것입니다") : :

이 메소드는 텍스트를 한 번 구문 분석하여 모든 "단어"의 목록을 얻습니다. 각 단어는 대상 단어의 사전에서 찾아보고 대상 단어 인 경우 계산됩니다. 취한 시간은 O (p) + o (t)이며 여기서 p는 단락의 크기이고 t는 대상 단어의 수입니다. 내 AHO-Corasick 솔루션을 제외한 현재까지의 다른 모든 솔루션 (현재 허용되는 솔루션 포함)은 O (PT)입니다.

def counts_all(targets, paragraph, word_regex=r"\w+"):
    tally = dict((target, 0) for target in targets)
    for word in re.findall(word_regex, paragraph):
        if word in tally:
            tally[word] += 1
    return [tally[target] for target in targets]

def counts_iter(targets, paragraph, word_regex=r"\w+"):
    tally = dict((target, 0) for target in targets)
    for matchobj in re.finditer(word_regex, paragraph):
        word = matchobj.group()
        if word in tally:
            tally[word] += 1
    return [tally[target] for target in targets] 

Finditer 버전은 Strawman입니다. Findall 버전보다 훨씬 느립니다.

다음은 표준화 된 형태로 표현되고 워드 구분 제로 보강 된 현재 인정 된 솔루션입니다.

def currently_accepted_solution_augmented(targets, paragraph):
    def tester(s): 
        def f(x):
            return len(re.findall(r"\b" + x + r"\b", s))
        return f
    return map(tester(paragraph), targets)

폐쇄에 따라 배 밖으로 나가면 다음으로 줄일 수 있습니다.

# acknowledgement:
# this is structurally the same as one of hughdbrown's benchmark functions
def currently_accepted_solution_augmented_without_extra_closure(targets, paragraph):
    def tester(x):
        return len(re.findall(r"\b" + x + r"\b", paragraph))
    return map(tester, targets)

현재 허용되는 솔루션의 모든 변형은 O (PT)입니다. 현재 허용되는 솔루션과 달리 Word Delimiters가있는 Regex 검색은 단순한 것과 같지 않습니다. paragraph.find(target). 이 경우 RE 엔진이 "빠른 검색"을 사용하지 않기 때문에 구분자라는 단어를 추가하면 느리게 변경됩니다. 매우 느린.

다른 팁

폐쇄는 빠른 해결책입니다.

paragraph = "I eat bananas and a banana"

def tester(s): 
    def f(x):
        return len(re.findall(x,s))
    return f

print map(tester(paragraph), ['banana', 'loganberry', 'passion fruit'])
targets = ['banana', 'loganberry', 'passion fruit']
paragraph = "I eat bananas and a banana"

print [paragraph.count(target) for target in targets]

왜 여기에서 map ()를 사용할 것인지 모르겠습니다.

나는 당신이 목록 이해를 요구하지 않았다는 것을 알고 있지만 여기서는 다음과 같습니다.

paragraph = "I eat bananas and a banana"
words = ['banana', 'loganberry', 'passion fruit']
[len(re.findall(word, paragraph)) for word in words]

이것은 [2, 0, 0]도 반환합니다.

이것은 기본적으로 목록 이해를 피하기 위해 길을 벗어나는 것입니다. 그러나 기능적 스타일 프로그래밍을 좋아한다면, 당신은 좋아할 것입니다. funcTools.Partial.

>>> from functools import partial
>>> def counter(text, paragraph):
    return len(re.findall(text, paragraph))

>>> tester = partial(counter, paragraph="I eat bananas and a banana")
>>> map(tester, ['banana', 'loganberry', 'passion fruit'])
[2, 0, 0]

크기 t 바이트의 큰 텍스트에서 평균 길이 l 바이트의 q 쿼리 단어의 경우 O (QLT)가 아닌 것이 필요합니다. 설정 후 O (T)를 제공 할 수있는 DFA 스타일의 접근 방식이 필요합니다. 쿼리 세트가 다소 정적 인 경우 설정 비용을 무시할 수 있습니다.

예를 들어 http://en.wikipedia.org/wiki/Aho-Corasick_algorithm
Python의 C- 확장을 가리 킵니다.
http://hkn.eecs.berkeley.edu/~dyoo/python/ahocorasick/

여기 내 버전이 있습니다.

paragraph = "I eat bananas and a banana"

def tester(paragraph, x): return len(re.findall(x,paragraph))

print lambda paragraph: map(
    lambda x: tester(paragraph, x) , ['banana', 'loganberry', 'passion fruit']
        )(paragraph)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top