【问题标题】:How to effeciently count string aliases?如何有效地计算字符串别名?
【发布时间】:2018-11-05 09:24:51
【问题描述】:

我正在从事一个个人项目,该项目计算文本中提到的名称实例。我知道我可以用collections.Counter() 做到这一点,但我不确定如何有效地考虑别名。

例如,假设我要计算的名字之一是"Tim",但我也想计算他的任何昵称,例如"Timmy""Timster"

我有一些字符串说,"Oh Tim is going to the party?""Yeah, my boy Timmy, wouldn't miss it, he loves to party!""Whoa, the Timster himself is going? Count me in!"

我想把它们都算作"Tim" 这样的变量。我知道我可以简单地单独计算它们,然后将计数加在一起。但我觉得有更好的方法可以做到这一点。

I.E.我希望我的代码看起来更像。

names = {
    'Tim':{'Tim', 'Timmy', 'Timster'},
    ... other names here.}
# add any occurrence of Tim names to Tim and other occurrences of other names to their main name.

相对于类似的东西

total_tim = Counter(tim) + Counter(timmy) + Counter(timster), etc..

每个名字。有谁知道我会怎么做?

【问题讨论】:

  • total_tim = Counter(tim) + Counter(timmy) + Counter(timster), etc.. 更直接,并且可能比添加间接更有效。您也许可以将这种方法包装到模仿您首选的方法中?
  • @ReblochonMasque 你确定吗?我打算跟踪几十个名字,感觉手动将它们全部加在一起感觉很草率。
  • 无论如何,您必须输入这些别名组,不是吗?例如,如果您将其包装在 class AliasCounter 中;该类可以采用text Counter,并按别名对其进行分组;不过,您仍然需要提供这些别名。
  • @ChristianDean 对不起,我不太确定如何做到这一点,而不必像我试图避免的那样手动将所有别名添加在一起。能举个例子吗?
  • 我已经有了解决方案。 (我可以简单地使用 Counter() 单独添加每个昵称,然后为每个名字说 Tim = Tim_Counter + Timmy_Counter + Timster_Counter 等等,但是在处理几十个名字时会占用很多行。)我是希望找到一个解决方案,可以只说“计算这个字典中所有昵称的出现次数,对于字典中的每个名字。”

标签: python python-3.x collections count counter


【解决方案1】:

这是一个使用正则表达式的非常简单的解决方案。

此解决方案的优点是您不必明确命名变体。如果你知道那个人名字的开头变体,你应该没问题。

from collections import Counter
import re

TEXT = '''
    Blah Tim blah blah Timmy blah Timster blah Tim
    Blah Bill blah blah William blah Billy blah Bill Bill
'''

tim_search = '(Tim([a-z]*)?(?=\ ?))'
bill_search = '((B|W)ill([a-z]*)?(?=\ ?))'
def name_counter(regex_string): 
   return Counter([i for i, *j in re.findall(regex_string, TEXT)])

name_counter(tim_search)
Counter({'Tim': 2, 'Timmy': 1, 'Timster': 1})

name_counter(bill search)
Counter({'Bill': 3, 'Billy': 1, 'William': 1})

【讨论】:

    【解决方案2】:

    使用正则表达式将有助于解决这个问题。

    import re
    your_dict = {"Tim":["Tim","Timmy","Timster"]}
    s = "Oh Tim is going to the party? Yeah, my boy Timmy, wouldn't miss it, he loves to party! Whoa, the Timster himself is going? Count me in!"
    for each in your_dict:
        print(each,"count = ", len(re.findall("|".join(sorted(your_dict[each],reverse=True)),s)))
    

    如果你想忽略大小写,那么只需在re.findall 中使用re.IGNORECASE 参数

    【讨论】:

      【解决方案3】:
      from collections import Counter
      
      TEXT = '''
          Blah Tim blah blah Timmy blah Timster blah Tim
          Blah Bill blah blah William blah Billy blah Bill Bill
      '''
      words = TEXT.split()
      
      # Base names a their aliases.
      ALIASES = dict(
          Tim = {'Tim', 'Timmy', 'Timster'},
          Bill = {'Bill', 'William', 'Billy'},
      )
      
      # Given any name, find its base name.
      BASE_NAMES = {a : nm for nm, aliases in ALIASES.items() for a in aliases}
      
      # All names.
      ALL_NAMES = set(nm for aliases in ALIASES.values() for nm in aliases)
      
      # Count up all names.
      detailed_tallies = Counter(w for w in words if w in ALL_NAMES)
      
      # Then build the summary counts from those details.
      summary_tallies = Counter()
      for nm, n in detailed_tallies.items():
          summary_tallies[BASE_NAMES[nm]] += n
      
      print(detailed_tallies)
      print(summary_tallies)
      
      # Counter({'Bill': 3, 'Tim': 2, 'Timmy': 1, 'Timster': 1, 'William': 1, 'Billy': 1})
      # Counter({'Bill': 5, 'Tim': 4})
      

      【讨论】:

      • 单词被空格分隔时会出现问题:'Tim, blah blah.'
      • @figbeam 当然,但这不是问题。
      • 这确实需要您明确命名每个别名。
      • @WStokvis 是的,但它们被命名为 data。它们没有编码在变量名中(例如total_tim = Counter(tim) + Counter(timmy) + Counter(timster))。
      • 这绝对不是一个有效的方法
      猜你喜欢
      • 2011-01-05
      • 2019-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多