11

#我正在寻找一种干净的方法来获取以给定字符串开头的一组(列表、数组等)单词。

在 C# 中,我会写

var hashtags = input
    .Split (' ')
    .Where (s => s[0] == '#')
    .Select (s => s.Substring (1))
    .Distinct ();

在 Python 中执行此操作的相对优雅的代码是什么?

编辑

样本输入:"Hey guys! #stackoverflow really #rocks #rocks #announcement"
预期输出:["stackoverflow", "rocks", "announcement"]

4

6 回答 6

24

使用@inspectorG4dget 的答案,如果您不想重复,您可以使用集合推导而不是列表推导。

>>> tags="Hey guys! #stackoverflow really #rocks #rocks #announcement"
>>> {tag.strip("#") for tag in tags.split() if tag.startswith("#")}
set(['announcement', 'rocks', 'stackoverflow'])

请注意,{ }集合推导的语法仅适用于从 Python 2.7 开始。
如果您使用的是旧版本,请按照@Bertrand 的建议[ ]运行提要列表理解 ( ) 输出。set

于 2011-06-13T14:20:37.883 回答
15
[i[1:] for i in line.split() if i.startswith("#")]

这个版本将摆脱任何空字符串(正如我在评论中读到这样的担忧)和只有"#". 此外,与Bertrand Marron的代码一样,最好将其转换为如下集合(以避免重复和 O(1) 查找时间):

set([i[1:] for i in line.split() if i.startswith("#")])
于 2011-06-13T14:09:03.087 回答
10

正则表达式对象findall方法可以一次获取所有对象:

>>> import re
>>> s = "this #is a #string with several #hashtags"
>>> pat = re.compile(r"#(\w+)")
>>> pat.findall(s)
['is', 'string', 'hashtags']
>>> 
于 2011-06-13T14:17:32.663 回答
8

我会说

hashtags = [word[1:] for word in input.split() if word[0] == '#']

编辑:这将创建一个没有任何重复的集合。

set(hashtags)
于 2011-06-13T14:08:54.600 回答
1

另一种选择是正则表达式:

import re

inputLine = "Hey guys! #stackoverflow really #rocks #rocks #announcement"

re.findall(r'(?i)\#\w+', inputLine) # will includes #
re.findall(r'(?i)(?<=\#)\w+', inputLine) # will not include #
于 2011-06-13T14:14:37.410 回答
1

这里提供的答案存在一些问题。

  1. {tag.strip("#") for tag in tags.split() if tag.startswith("#")}

    [i[1:] for i in line.split() if i.startswith("#")]

如果您有像“#one#two#”这样的标签,则无法使用

2re.compile(r"#(\w+)")不适用于许多 unicode 语言(即使使用 re.UNICODE)

我已经看到了更多提取主题标签的方法,但发现它们都没有回答所有情况

所以我写了一些小的python代码来处理大多数情况。这个对我有用。

def get_hashtagslist(string):
    ret = []
    s=''
    hashtag = False
    for char in string:
        if char=='#':
            hashtag = True
            if s:
                ret.append(s)
                s=''           
            continue

        # take only the prefix of the hastag in case contain one of this chars (like on:  '#happy,but i..' it will takes only 'happy'  )
        if hashtag and char in [' ','.',',','(',')',':','{','}'] and s:
            ret.append(s)
            s=''
            hashtag=False 

        if hashtag:
            s+=char

    if s:
        ret.append(s)

    return set(ret)
于 2015-09-10T09:55:11.073 回答