2016-03-11 2 views
2

У меня есть сообщение, какРасщепление строк данных в ключевых слов в Python в индивидуальных целях и хранения определенных ключевых слов отдельно

message= "Hello #world I am in #London and it is #sunny today it is #2016" 

Мне нужно 2 массивы из этого сообщения следует быть слова который расщепляется слова и (не Хештеги) только до появления второго хэштегом и нет необходимости хранить остальную часть слова после второго хэштегом в качестве ключевых слов, как:

key words:`['Hello','I','am','in']` 

также мне нужно хранить все хештегов в их возникновения заказов в сообщении:

tags: `['#world','#London','#sunny','#2016']` 

разделить слова до появления второго хэштегом Я использую следующий код:

i=message.find("#",str(row[0]).find("#")+1) 
words=re.sub(r'[)|*&$^(;!][,]', r' ',(message)[:i])).split() 

проблема является что в этом случае у меня все еще есть первый хэштегов в словах !?

Также мне нужно построить массив как теги в Python?

ответ

1

Вот решение, которое использует itertools.groupby из станда Lib:

from itertools import groupby 

is_hashtag = lambda w: w.startswith('#') and len(w)>1 

tests = """\ 
    Hello #world I am in #London and it is #sunny today it is #2016 
    Hello #London I am in #London and it is #sunny today it is #2016 
    Hello #Austin I am at #SXSW and this is just a # hashtag symbol""" 

for t in tests.splitlines(): 
    t = t.strip() 
    groups = groupby(t.split(), key=is_hashtag) 

    tags = [] 
    keywords = [] 

    # get words up to first hashtag 
    ishash, words = next(groups) 
    keywords.extend(list(words)) 

    # get first hashtag 
    ishash, tag = next(groups) 
    tags.extend(list(tag)) 

    # get words up to next hashtag 
    ishash, words = next(groups) 
    keywords.extend(list(words)) 

    # get all remaining hashtags 
    for ishash, tag in groups: 
     if ishash: 
      newtags = list(tag) 
      tags.extend(newtags) 

    print (t) 
    print (tags) 
    print (keywords) 
    print ('') 

Основная функция переключает группирования состояния, возвращая все слова, которые не Хештег, или все слова, которые Хештег.

Печать:

Hello #world I am in #London and it is #sunny today it is #2016 
['#world', '#London', '#sunny', '#2016'] 
['Hello', 'I', 'am', 'in'] 

Hello #London I am in #London and it is #sunny today it is #2016 
['#London', '#London', '#sunny', '#2016'] 
['Hello', 'I', 'am', 'in'] 

Hello #Austin I am at #SXSW and this is just a # hashtag symbol 
['#Austin', '#SXSW'] 
['Hello', 'I', 'am', 'at'] 
+0

Большое вам спасибо, единственная проблема в том, что этот метод не может заметить хэштеги, если они являются самым первым словом сообщений, например, если это «#Hello #worlds I am ...» !! – Far

+0

Очистка логики оставлена ​​как упражнение для вопроса плаката – PaulMcG

+0

:) Конечно! спасибо за помощь, которую вы предоставили – Far

2

Вы можете сделать это, используя str.split и list comprehensions вместо регулярного выражения. Алгоритм это

  • Разделить сообщение на части и используя список понимание фильтр теги
  • Используя второй тег, вырезать первое сообщение
  • Снова используя список понимание, найти ключевые слова.

>>> message= "Hello #world I am in #London and it is #sunny today it is #2016" 
>>> tags = [i for i in message.split() if i[0]=='#'] 
>>> temp_message = message.split(tags[1])[0] 
>>> key_words = [i for i in temp_message.split() if i[0]!='#'] 
>>> tags 
['#world', '#London', '#sunny', '#2016'] 
>>> key_words 
['Hello', 'I', 'am', 'in'] 
+0

спасибо, как я могу разделить, а не белое пространство также с другими персонажами, как '[) | * &$^(;!] [,]' В этом случае? – Far

+0

@Farimah Прочтите связанный документ, он будет более полезен ... Вы можете использовать 'split ('[')' ie, передать параметр функции 'split' :-) –

+0

Я не заметил вас положите ссылку спасибо много :) – Far

0

Я бы первый разбить строку в список слов, а затем перебрать эти слова, добавляя слова в списке справа (с помощью StartsWith() функции):

message_list = message.split() 
tags = [] 
notags = [] 
for e in message_list: 
    if e.startswith('#'): 
     tags.append(e) 
    else: 
     notags.append(e) 
0

Вот еще одно решение.

import re 

string = "Hello #world I am in #London and it is #sunny today it is #2016" 

#get hash tags only list 
list_hash_tags = re.findall(r'#\S+', string) 
print(list_hash_tags) 

#use second element in hash tag list to get string match up to second match 
list_keywords_step0 = re.findall(r'^.*?(?=' + list_hash_tags[1] + r')', string) 
list_keywords_step0[0] = re.sub(r'#\w+\W+', '', list_keywords_step0[0]) 

#get keywords 
list_keywords = list_keywords_step0[0].split() 
print(list_keywords) 

Выход:

['#world', '#London', '#sunny', '#2016'] 
['Hello', 'I', 'am', 'in'] 
+0

Что делать, если строка ввода «Здравствуйте, #London, я нахожусь в #London, и это #sunny сегодня это # ​​2016»? – PaulMcG

+0

К сожалению, поскольку первый и второй хэштеги одинаковы, ваш вызов 're.findall' для получения второго тега фактически находит первый, поэтому ваш список ключевых слов содержит только' ['Hello'] ', а не' [' Hello ',' I ',' am ',' in '] '. – PaulMcG

+0

@PaulMcGuire - вы правы, спасибо за тест. - [link] (http://stackoverflow.com/users/5757880/deepak-nagarajan) –

1

Можно подумать, что синтаксический анализатор является излишеством для этой проблемы, но если вы используете один, то вам будет лучше в состоянии справиться с неизбежным «ой, есть еще один незначительные изменения в формате «изменения, которые придут.

Вот Pyparsing решение Вашего вопроса:

from pyparsing import Word, printables, ZeroOrMore, OneOrMore 

hashword = Word('#', printables, min=2)("hashtag*") 
word = ~hashword + Word(printables) 

msg = (ZeroOrMore(word)("leading") + 
     hashword + 
     OneOrMore(word)("internal") + 
     hashword + 
     ZeroOrMore(hashword | word)("trailing")) 


tests = """\ 
    Hello #world I am in #London and it is #sunny today it is #2016 
    Hello #London I am in #London and it is #sunny today it is #2016 
    Hello #Austin I am at #SXSW and this is just a # hashtag symbol""" 

msg.runTests(tests) 

# show how to access the named results in the parsed output 
for t in tests.splitlines(): 
    fields = msg.parseString(t) 
    print(fields.hashtag) 

hashword определяет слово, начинающееся с «#», и имеет, по меньшей мере, один дополнительный символ. ("hashtag*") будет служить для сбора всех хэштегов в сообщении в одно имя результата. word определяет слово любых символов, если оно не является hashword.Определение msg определяет все части указанного вами сообщения и присваивает разные части именам leading, internal и trailing.

Наконец, маленький цикл for-loop в конце показывает, как получить доступ к различным именованным результатам, возвращенным из вызова, до parseString().

Вот что это выводит:

Hello #world I am in #London and it is #sunny today it is #2016 
['Hello', '#world', 'I', 'am', 'in', '#London', 'and', 'it', 'is', '#sunny', 'today', 'it', 'is', '#2016'] 
- hashtag: ['#world', '#London', '#sunny', '#2016'] 
- internal: ['I', 'am', 'in'] 
- leading: ['Hello'] 
- trailing: ['and', 'it', 'is', '#sunny', 'today', 'it', 'is', '#2016'] 
    - hashtag: ['#sunny', '#2016'] 

Hello #London I am in #London and it is #sunny today it is #2016 
['Hello', '#London', 'I', 'am', 'in', '#London', 'and', 'it', 'is', '#sunny', 'today', 'it', 'is', '#2016'] 
- hashtag: ['#London', '#London', '#sunny', '#2016'] 
- internal: ['I', 'am', 'in'] 
- leading: ['Hello'] 
- trailing: ['and', 'it', 'is', '#sunny', 'today', 'it', 'is', '#2016'] 
    - hashtag: ['#sunny', '#2016'] 

Hello #Austin I am at #SXSW and this is just a # hashtag symbol 
['Hello', '#Austin', 'I', 'am', 'at', '#SXSW', 'and', 'this', 'is', 'just', 'a', '#', 'hashtag', 'symbol'] 
- hashtag: ['#Austin', '#SXSW'] 
- internal: ['I', 'am', 'at'] 
- leading: ['Hello'] 
- trailing: ['and', 'this', 'is', 'just', 'a', '#', 'hashtag', 'symbol'] 

['#world', '#London', '#sunny', '#2016'] 
['#London', '#London', '#sunny', '#2016'] 
['#NewYork', '#SXSW'] 

EDIT

Если вы не уверены в том, что входная строка фактически содержит хештегов и слова в форме вы описываете, вы можете расширить парсер определение принимает практически любую комбинацию хэштегов и слов в качестве резервной копии:

msg = (ZeroOrMore(word)("leading") + 
     hashword + 
     OneOrMore(word)("internal") + 
     hashword + 
     ZeroOrMore(hashword | word)("trailing") 
     | 
     # use this expression to just get whatever hashtags are to be found 
     OneOrMore(hashword | word)) 

Вторая часть анализатора просто соберет все хэштеги в имя результата «hashtag», а остальные имена («ведущие» и т. д.) будут неопределенными.

+0

спасибо, что я пытаюсь применить ваш код, и я столкнулся с этой ошибкой: «AttributeError:« И »объект не имеет атрибута« runTests », «как вы можете догадаться, я довольно новичок в Python, мне непонятно, почему я здесь столкнулся с этим? – Far

+0

runTests была добавлена ​​в недавней версии pyparsing. Убедитесь, что вы используете последнюю версию, используя 'pip install -U pyparsing' – PaulMcG

+0

Эта ошибка заключается в том, что синтаксический анализатор ищет хэштег (слово, начинающееся с« # », за которым следуют печатные материалы) и доходит до столбца 829 и не найдя его! Я подозреваю, что это очень длинная строка ввода и что она не соответствует вашему ожидаемому формату. Распечатайте строку, в которой она не работает, и убедитесь, что в ней есть не менее 2 хэштегов. – PaulMcG

Смежные вопросы