1

Pythonで、リスト内の各アイテムが文字列に含まれる回数を取得しようとしています。

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以上のメンバーが含まれます。私の考えでは、マップは並行して動作するため、どのシリアルメソッドよりもはるかに効率的です。

4

7 に答える 7

8

閉鎖は迅速な解決策になります:

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'])
于 2009-07-22T21:57:41.173 に答える
3
targets = ['banana', 'loganberry', 'passion fruit']
paragraph = "I eat bananas and a banana"

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

ここで map() を使用する理由がわかりません。

于 2009-07-22T23:06:47.583 に答える
2

リストの理解を求めていないことは知っていますが、とにかくここにあります:

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

これも [2, 0, 0] を返します。

于 2009-07-22T22:34:55.683 に答える
2

これは基本的に、リスト内包表記を避けるために道を外れているだけですが、関数型のプログラミングが好きなら、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]
于 2009-07-22T23:19:36.607 に答える
1

ゴールポストの動きに対する応答は次のとおりです (「近い将来単語の区切り記号が必要になるため、おそらく正規表現が必要です」)。

このメソッドは、テキストを 1 回解析して、すべての「単語」のリストを取得します。各単語は対象語の辞書で調べられ、対象語であればカウントされます。かかる時間は 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 バージョンはストローマンです。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) です。現在受け入れられている解決策とは異なり、単語区切り文字を使用した正規表現検索は、単純な と同等ではありませんparagraph.find(target)。この場合、re エンジンは「高速検索」を使用しないため、単語区切り文字を追加すると、低速から非常に低速に変更されます。

于 2009-07-24T03:21:15.057 に答える
1

サイズ 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/

于 2009-07-23T15:58:19.440 に答える
0

これが私のバージョンです。

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)
于 2009-07-22T23:16:55.847 に答える