Элегантный способ получить хэштеги из строки в Python? - PullRequest
7 голосов
/ 13 июня 2011

Я ищу чистый способ получить набор (список, массив, что угодно) слов, начинающихся с # внутри данной строки.

В C # я бы написал

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

Что такое сравнительно элегантный код для этого в Python?

EDIT

Пример ввода: "Hey guys! #stackoverflow really #rocks #rocks #announcement"
Ожидаемый результат: ["stackoverflow", "rocks", "announcement"]

Ответы [ 6 ]

19 голосов
/ 13 июня 2011

С ответом @ 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.
Если вы работаете с более старыми версиями, вывод списка рассылки ([ ]) в set выводится как , предложенный @ Bertrand .

15 голосов
/ 13 июня 2011
[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("#")])
8 голосов
/ 13 июня 2011

метод findall объектов регулярных выражений может получить их все сразу:

>>> import re
>>> s = "this #is a #string with several #hashtags"
>>> pat = re.compile(r"#(\w+)")
>>> pat.findall(s)
['is', 'string', 'hashtags']
>>> 
7 голосов
/ 13 июня 2011

Я бы сказал

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

Редактировать: это создаст набор без дубликатов.

set(hashtags)
1 голос
/ 13 июня 2011

Другой вариант - regEx:

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 #
0 голосов
/ 10 сентября 2015

Есть некоторые проблемы с ответами, представленными здесь.

  1. {tag.strip ("#") для тега в tags.split (), если tag.startswith ("#")}

    [i [1:] для i в line.split (), если i.startswith ("#")]

не будет работать, если у вас есть хэштег, как '# one # two #'

2 re.compile(r"#(\w+)") не будет работать для многих языков Юникода (даже с использованием 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)
...