Loop nested in python

1

I'm trying to create a nested loop to check a list of words in a list of texts, but the loop does not work as expected.

palabra=["cefalea", "hemicraneal", "días"]
hc="cefalea hemicraneal derecha de 4 días de evolución"
hc2="Hombre con cefalea y ganas de dormir"
texto=[hc,hc2]
n=2
m=1
contador=[0,0,0]
for i in range(0,n):
    for j in range(0,m):
        if texto[j].find(palabra[i]):
            contador[i]=1
            print(contador)

Any suggestions?

    
asked by Daniel Starlord 06.07.2017 в 20:47
source

2 answers

2

I'm not sure I know the reason why you use the variables n and m . If your variable texto is a list of sentences you could simply iterate that list and count the words for each sentence. On the other hand, the%% co_% will return str.find if it does not find the word, so your -1 sentence will increase your counter since if is evaluated as a true value:

>>> valor = -1
>>> if valor:
...   print 'Verdadero'
... 
Verdadero
>>>

First of all what I would do would be to put everything together in one text:

>>> hc="cefalea hemicraneal derecha de 4 días de evolución"
>>> hc2="Hombre con cefalea y ganas de dormir"
>>> texto = ' '.join([hc, hc2])
>>> print texto
cefalea hemicraneal derecha de 4 días de evolución Hombre con cefalea y ganas de dormir

Now, to count you could use a dictionary:

>>> contador = {}
>>> for p in texto.split():
...     if p not in contador:
...         contador[p] = 0
...     contador[p] += 1
... 
>>> contador
{'hemicraneal': 1, 'dormir': 1, 'evoluci\xc3\xb3n': 1, 'de': 3, 'cefalea': 2, 'derecha': 1, 'ganas': 1, '4': 1, 'Hombre': 1, 'y': 1, 'con': 1, 'd\xc3\xadas': 1}
>>> contador.get('cefalea', 0)
2
>>> contador.get('esternocleidomastoideo', 0)
0

You can also use the -1 class in the Counter library:

>>> from collections import Counter
>>> contador = Counter(texto.split())
>>> contador
Counter({'de': 3, 'cefalea': 2, 'hemicraneal': 1, 'dormir': 1, 'evoluci\xc3\xb3n': 1, 'derecha': 1, 'ganas': 1, '4': 1, 'Hombre': 1, 'y': 1, 'con': 1, 'd\xc3\xadas': 1})
>>> contador['cefalea']
2
>>> contador['esternocleidomastoideo']
0
    
answered by 06.07.2017 в 21:20
2

In the code that you published, I see some errors that I will detail:

Problem with the range

First, note that list(range(0,1)) does not return [0,1] , but [0] , this is why the definition of this function is class range(start, stop[, step]) , the parameter stop does not work as in other languages where what is expected is to indicate the value "up", but it is the value where this function will stop, that is, it is a < stop , that is, when you do:

for i in range(0,n):
    for j in range(0,m):

What you achieve is to go through the lists until the next to last element, in fact the correct thing would be:

for i in range(0, n + 1):
    for j in range(0, m + 1):

Problems arising from the use of the find

I already told you Cesar , find returns the position where the searched string was found and -1 if not done, and the -1 in Python is evaluated as Verdadero , also if it finds the string in the first position, as is going to be 0, then the 0 is evaluated as False , that is, it will never work as expected. The right thing to do if you want to use find , would do it like this: if texto[j].find(palabra[i]) >= 0: . Additionally, as I commented just a short while ago FJSevilla this function will find the desired value within other words, for example "alcaldía".find("día") will be evaluated as True, with which for the use you want giving does not work. It's better to search directly by words, so you should do a split() of each text and do something like this: if palabra[i] in texto[j].split()

contador

I do not see the meaning of this variable as you are completing it, I understand that what you want is a final counter for each of the three words, but doing contador[i]=1 you are not accumulating and in the order of the cycles I can not deduce that you are looking for a word counter for each text. In case you look for a total counter you should accumulate doing contador[i]=contador[i]+1 or in its most limited version contador[i]+=1 .

With these observations your code would be as follows:

palabra=["cefalea", "hemicraneal", "días"]
hc="cefalea hemicraneal derecha de 4 días de evolución"
hc2="Hombre con cefalea y ganas de dormir"
texto=[hc,hc2]
n=2
m=1
contador=[0,0,0]
for i in range(0,n+1):
    for j in range(0,m+1):
        if palabra[i] in texto[j].split():
            contador[i]+=1
print(contador)

The final return will be:

[2, 1, 1]

This kind of things in Python are usually solved in a much simpler way and they say "Pythonica". The response of Cesar goes in that direction and I think the use of Counter is the best way to solve it. I'm just going to add one more using list comprehension, a Python technique that distinguishes it as a language:

palabra = ["cefalea", "hemicraneal", "días"]
hc = "cefalea hemicraneal derecha de 4 días de evolución"
hc2 = "Hombre con cefalea y ganas de dormir"
texto = [hc,hc2]

contador = [0, 0, 0]
for f in texto:
  contador =  [x + y for x, y in zip(contador, [1 if p in f.split() else 0 for p in palabra])]

print(contador)

The interesting thing is how much logic can be indicated in a single line, let's see:

[1 if p in f.split() else 0 for p in palabra] with this we return a list where for each words we will have a 1 if it was found in the text or a 0 otherwise, that is to say something like [1, 0, 0] if only it had found "cefalea" . We would have to adapt it if we also want to add the repetitions in the same text, but by your code I understand that you are not looking for that. the following is zip(contador, ...) , zip weapon tuples with an item of each of the lists in order, that is if we combine in this way [1, 1, 0] and [1, 0, 0] we will obtain [(1, 1), (1, 0), (0, 0)] , so then when doing [x + y for x, y in zip(...] we end up adding the values of each tuple and accumulating on the list contador the list indicative of the found values.

    
answered by 07.07.2017 в 00:18