【问题标题】:Hashtag counter PythonHashtag 计数器 Python
【发布时间】:2020-07-18 00:30:14
【问题描述】:

我是 python 初学者。对于一个练习,我必须编写一个 python 函数来扫描字符串列表,计算主题标签出现的次数并将其放入字典中。示例:

[
    "hi #weekend",
    "good morning #zurich #limmat",
    "spend my #weekend in #zurich",
    "#zurich <3"
]

分析这个列表后,函数应该返回:

{'weekend': 2, 'zurich': 3, 'limmat': 1}

只允许使用字母和数字,其他任何内容,如空格和句点,都可以结束标签。

我们可以假设参数始终是一个有效的字符串列表,您不需要提供任何类型的输入验证。

标签是针对特定情况的。 #ZURICH 应被视为与 #zurich 不同的主题标签。


我有一个丑陋的函数初稿,如果字符串中有多个主题标签,它就不起作用,因为它会跳过第二个。我不一定需要关于如何简化函数或使其更 Pythonic 的提示(当然它仍然会受到赞赏)。我只是想知道为什么它不起作用。


def analyze(posts):
    hashtag_dict = {}
    for post_string in posts:
        for char in post_string:
            if char == "#":
                hash_index = post_string.find(char)
                counter = 1
                tag = ""
                for tag_char in post_string[hash_index + 1:]:
                    if tag_char.isdigit() or tag_char.isalpha():
                        tag += tag_char
                    elif tag in hashtag_dict:
                        counter += 1
                        hashtag_dict[tag] = counter
                        break
                    else:
                        hashtag_dict[tag] = counter
                        break
    return hashtag_dict


posts = [
        "hi #weekend",
        "good morning #zurich #limmat",
        "spend my #weekend in #zurich",
        "#zurich <3"]

print(analyze(posts))


任何帮助将不胜感激!

【问题讨论】:

  • 尝试阅读regular expressions。我认为只需几行代码就可以解决您的问题。
  • 这个正则表达式会找到你的标签值,然后你可以计算它们\#([^ ]+),因为会发现“除了空格之外的任何东西”

标签: python


【解决方案1】:

从根本上说,你的函数不起作用,因为这条线

hash_index = post_string.find(char)

总是会在字符串中找到 first 哈希标签的索引。这可以通过提供start index to str.find 来解决,或者更好的是,根本不调用str.find,而是在遍历字符串时维护索引(您可以为此使用enumerate)。更好的是,不要使用索引,如果您将解析器重构为使用状态机,则不需要它。

也就是说,Pythonic 实现将用regular expression 替换整个函数,这将大大缩短、正确、更易读,并且可能更高效。

【讨论】:

  • 感谢您的帮助!我认为我们应该只使用到目前为止我们在课程中学到的东西来做这个练习。我们还没有进入正则表达式。我会尝试用你的建议来解决它!
【解决方案2】:

这应该可行:

import string
alpha = string.ascii_letters + string.digits

def analyze(posts):
    hashtag_dict = {}

    for post in posts:
        for i in post.split():
            if i[0] == '#':
                current_hashtag = sanitize(i[1:])

                if len(current_hashtag) > 0:
                    if current_hashtag in hashtag_dict:
                        hashtag_dict[current_hashtag] += 1
                    else:
                        hashtag_dict[current_hashtag] = 1

    return hashtag_dict


def sanitize(s):
    s2 = ''
    for i in s:
        if i in alpha:
            s2 += i
        else:
            break
    return s2


posts = [
        "hi #weekend",
        "good morning #zurich #limmat",
        "spend my #weekend in #zurich",
        "#zurich <3",
        "#lindehof4Ever(lol)"
        ]

print(analyze(posts))

【讨论】:

  • 非常感谢!这似乎在某些情况下有效。但是,除数字或字母之外的任何内容都应结束主题标签。因此,如果有人像#zurich(in switzerland) 这样写,则主题标签只能是“zurich”而不是“zurich(in”或其他任何内容。字典中也不应该出现空主题标签。如果有人简单地写“#”,则不应有任何条目完全可以做到。
  • 嗯好吧,我们可以为这个想法添加条件我不确定这是最佳实践
  • @Kajice 现在应该可以按预期工作,并确保我们只选择标签(即,如果你有 he#lo 它现在不会被识别为标签
【解决方案3】:

在您的帮助下,我设法获得了 2.75 分(满分 4 分)。非常感谢!我没有将您的任何解决方案复制粘贴到更正工具中,我使用了自己的版本,并尝试根据您的建议进行改进。 (我敢肯定,如果我发布您的任何解决方案,我会得到 4/4。)

根据他们的说法,官方的解决方案是:

def analyze(posts):
tags = {}

for post in posts:
    curHashtag = None
    for c in post:
        is_allowed_char = c.isalnum()

        if curHashtag != None and not is_allowed_char:
            if len(curHashtag) > 0 and not curHashtag[0].isdigit():
                if curHashtag in tags.keys():
                    tags[curHashtag] += 1
                else:
                    tags[curHashtag] = 1
            curHashtag = None

        if c == "#":
            curHashtag = ""
            continue

        if c.isalnum() and curHashtag != None:
            curHashtag += c

    if curHashtag != None:
        if len(curHashtag) > 0 and not curHashtag[0].isdigit():
            if curHashtag in tags.keys():
                tags[curHashtag] += 1
            else:
                tags[curHashtag] = 1

return tags

这当然不是一个优雅的解决方案,而是一个完全使用我们目前所学知识的解决方案。也许这可以帮助另一个想要使用他们拥有的工具来解决这个练习的初学者。

【讨论】:

    【解决方案4】:

    嗯,

    这个任务可以用正则表达式来完成,不要害怕使用它们;) 一些快速的解决方案。

    #!/usr/bin/python3.4
    import re
    
    PATTERN = re.compile(r'#(\w+)')
    posts = [
        "hi #weekend",
        "good morning #zurich #limmat",
        "spend my #weekend in #zurich",
        "#zurich <3"]
    
    container = {}
    for post in posts:
        for element in PATTERN.findall(elements):
            container[element] = container.get(element, 0) + 1
    print(container)
    

    结果:

    {'zurich': 3, 'limmat': 1, 'weekend': 2} 
    

    编辑

    我也想在这里使用来自集合的计数器。

    #!/usr/bin/python3.4
    import re
    from collections import Counter
    
    PATTERN = re.compile(r'#(\w+)')
    posts = [
        "hi #weekend",
        "good morning #zurich #limmat",
        "spend my #weekend in #zurich",
        "#zurich <3"]
    
    words = [word for post in posts for word in PATTERN.findall(post)]
    
    counted = Counter(words)
    print(counted)
    
    # Result: Counter({'zurich': 3, 'weekend': 2, 'limmat': 1})
    

    【讨论】:

      猜你喜欢
      • 2016-10-14
      • 2015-03-12
      • 1970-01-01
      • 2017-12-29
      • 2015-10-30
      • 1970-01-01
      • 1970-01-01
      • 2017-11-24
      • 2017-04-02
      相关资源
      最近更新 更多