2016-02-10 1 views
1

J'écris un programme pour diviser les mots contenus dans un hashtag.Utiliser une fonction comme argument pour re.sub dans Python?

Par exemple, je veux diviser les hashtags:

#Whatthehello #goback 

dans:

What the hello go back 

Je vais avoir des problèmes lors de l'utilisation re.sub avec un argument fonctionnel.

Le code que j'ai écrit est:

import re,pdb 

def func_replace(each_func): 
    i=0 
    wordsineach_func=[] 
    while len(each_func) >0: 
     i=i+1 
     word_found=longest_word(each_func) 
     if len(word_found)>0: 
      wordsineach_func.append(word_found) 
      each_func=each_func.replace(word_found,"") 
    return ' '.join(wordsineach_func) 

def longest_word(phrase): 
    phrase_length=len(phrase) 
    words_found=[];index=0 
    outerstring="" 
    while index < phrase_length: 
     outerstring=outerstring+phrase[index] 
     index=index+1 
     if outerstring in words or outerstring.lower() in words: 
      words_found.append(outerstring) 
    if len(words_found) ==0: 
     words_found.append(phrase) 
    return max(words_found, key=len)   

words=[] 
# The file corncob_lowercase.txt contains a list of dictionary words 
with open('corncob_lowercase.txt') as f: 
    read_words=f.readlines() 

for read_word in read_words: 
    words.append(read_word.replace("\n","").replace("\r","")) 

Par exemple lorsque vous utilisez ces fonctions comme celle-ci:

s="#Whatthehello #goback" 

#checking if the function is able to segment words 
hashtags=re.findall(r"#(\w+)", s) 
print func_replace(hashtags[0]) 

# using the function for re.sub 
print re.sub(r"#(\w+)", lambda m: func_replace(m.group()), s) 

La sortie est-je obtenir:

What the hello 
#Whatthehello #goback 

Ce qui est pas la sortie que j'avais prévu:

What the hello 
What the hello go back 

Pourquoi cela se produit-il? En particulier, j'ai utilisé la suggestion de this answer mais je ne comprends pas ce qui ne va pas dans ce code.

+0

Hmmm .. quel est le problème. Pourquoi la downvote? Il s'agit de programmation !! –

+0

C'est bon d'être syntéthique mais votre question devrait au moins être lisible. Utilisez des phrases en anglais et non des résumés tels que "but: do this Code: ..; output ..; pourquoi? Voir ici". – Bakuriu

+0

@Bakuriu Merci pour le montage! Je le ferai en me demandant à nouveau. –

Répondre

1

Notez que m.group() renvoie l'intégralité de la chaîne qui correspond, si oui ou non il faisait partie d'un groupe de capture:

In [19]: m = re.search(r"#(\w+)", s) 

In [20]: m.group() 
Out[20]: '#Whatthehello' 

m.group(0) renvoie également tout le match:

In [23]: m.group(0) 
Out[23]: '#Whatthehello' 

En revanche, m.groups() renvoie tous les groupes de capture:

In [21]: m.groups() 
Out[21]: ('Whatthehello',) 

et m.group(1) renvoie le premier groupe de capture:

In [22]: m.group(1) 
Out[22]: 'Whatthehello' 

Le problème dans votre code provient de l'utilisation de m.group dans

re.sub(r"#(\w+)", lambda m: func_replace(m.group()), s) 

depuis

In [7]: re.search(r"#(\w+)", s).group() 
Out[7]: '#Whatthehello' 

alors que si vous aviez utilisé .group(1) , vous auriez eu

In [24]: re.search(r"#(\w+)", s).group(1) 
Out[24]: 'Whatthehello' 

et l'# précédent fait toute la différence:

In [25]: func_replace('#Whatthehello') 
Out[25]: '#Whatthehello' 

In [26]: func_replace('Whatthehello') 
Out[26]: 'What the hello' 

Ainsi, en changeant m.group()-m.group(1), et son remplacement par /usr/share/dict/words pour corncob_lowercase.txt,

import re 

def func_replace(each_func): 
    i = 0 
    wordsineach_func = [] 
    while len(each_func) > 0: 
     i = i + 1 
     word_found = longest_word(each_func) 
     if len(word_found) > 0: 
      wordsineach_func.append(word_found) 
      each_func = each_func.replace(word_found, "") 
    return ' '.join(wordsineach_func) 


def longest_word(phrase): 
    phrase_length = len(phrase) 
    words_found = [] 
    index = 0 
    outerstring = "" 
    while index < phrase_length: 
     outerstring = outerstring + phrase[index] 
     index = index + 1 
     if outerstring in words or outerstring.lower() in words: 
      words_found.append(outerstring) 
    if len(words_found) == 0: 
     words_found.append(phrase) 
    return max(words_found, key=len) 

words = [] 
# corncob_lowercase.txt contains a list of dictionary words 
with open('/usr/share/dict/words', 'rb') as f: 
    for read_word in f: 
     words.append(read_word.strip()) 
s = "#Whatthehello #goback" 
hashtags = re.findall(r"#(\w+)", s) 
print func_replace(hashtags[0]) 
print re.sub(r"#(\w+)", lambda m: func_replace(m.group(1)), s) 

impressions

What the hello 
What the hello gob a c k 

puisque, hélas, 'gob' est plus long que 'go'.


Une façon vous pouvez déboguée est de remplacer la fonction lambda avec une fonction régulière, puis ajouter des instructions d'impression:

def foo(m): 
    result = func_replace(m.group()) 
    print(m.group(), result) 
    return result 

In [35]: re.sub(r"#(\w+)", foo, s) 
('#Whatthehello', '#Whatthehello') <-- This shows you what `m.group()` and `func_replace(m.group())` returns 
('#goback', '#goback') 
Out[35]: '#Whatthehello #goback' 

Ce serait concentrer votre attention sur

In [25]: func_replace('#Whatthehello') 
Out[25]: '#Whatthehello' 

que vous pourriez ensuite comparer avec

In [26]: func_replace(hashtags[0]) 
Out[26]: 'What the hello' 

In [27]: func_replace('Whatthehello') 
Out[27]: 'What the hello' 

Cela vous amènerait à poser la question, si m.group() renvoie '#Whatthehello', quelle méthode dois-je retourner 'Whatthehello'. Une plongée dans the docs résout ensuite le problème.

+0

Merci! C'est la réponse la mieux expliquée que j'ai lue jusqu'ici. –