باستخدام خريطة() للحصول على عدد مرات قائمة العناصر الموجودة في سلسلة في بايثون

StackOverflow https://stackoverflow.com/questions/1168517

  •  19-09-2019
  •  | 
  •  

سؤال

أنا أحاول الحصول على عدد مرات كل بند في القائمة في سلسلة في بايثون:

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]

ما أود أن تفعل ذلك هو توسيع هذا حتى أستطيع أن أطعم الفقرة القيمة في الخريطة() وظيفة.الآن اختبار() وظيفة لديها الفقرة ضمنية.هل لدى أحدكم طريقة للقيام بذلك (ربما جعل n-طول قائمة الفقرة القيم)?أي أفكار أخرى هنا ؟

نضع في اعتبارنا أن كل من قيم مجموعة سيكون لها وزن في بعض نقطة في المستقبل - ومن ثم الحاجة إلى الحفاظ على القيم الموجودة في قائمة بدلا من الطحن لهم جميعا معا.

تحديث:الفقرة غالبا ما تكون 20K والقائمة غالبا ما يكون 200+ أعضاء.تفكيري هو أن خريطة تعمل في موازاة ذلك - لذلك سوف تكون أكثر كفاءة من أي مسلسل الأساليب.

هل كانت مفيدة؟

المحلول

إليك استجابة لحركة المراسضة ("ربما أحتاج إلى Regex لأنني سأحتاج إلى محاكي Word في المستقبل القريب"):

تقوم هذه الطريقة بتوزيع النص مرة واحدة للحصول على قائمة بجميع "الكلمات". يتم البحث عن كل كلمة في قاموس الكلمات المستهدفة، وإذا كانت كلمة مستهدفة يتم حسابها. الوقت المستغرق هو 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] 

الإصدار fatiter هو ستراما - إنه أبطأ بكثير من إصدار البحث.

إليك الحل المقبول حاليا تم التعبير عنها في شكل موحد ومزاجمه مع محددات Word:

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). على عكس الحل المقبول حاليا، فإن البحث Regex مع محددات Word لا يعادل بسيطة paragraph.find(target). وبعد نظرا لأن المحرك RE لا يستخدم "البحث السريع" في هذه الحالة، فإن إضافة Word Delimiters يغيره Fron Fron جداً بطيء.

نصائح أخرى

سيكون الإغلاق حلا سريعا:

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]

لا فكرة لماذا تستخدم الخريطة () هنا.

أعلم أنك لم تسأل عن فهم قائمة، ولكن هنا على أي حال:

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]

ف كلمات الاستعلام من متوسط طول L بايت على النصوص الكبيرة من حجم T بايت, كنت بحاجة إلى شيء ليس O(QLT).كنت في حاجة الى وزارة الخارجية على غرار النهج التي يمكن أن تعطيك O(T) ...بعد تكاليف الإعداد.إذا كان الاستعلام الخاص بك مجموعة ثابتة إلى حد ما ، ثم الإعداد التكلفة يمكن تجاهلها.

E. g. http://en.wikipedia.org/wiki/Aho-Corasick_algorithm
مما يشير إلى ج-امتداد بايثون:
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