J'ai à nouveau besoin des conseils avisés de Stack Overflow. Je ne suis pas sûr que le titre montre correctement ce que je me demande en ce moment.
Le problème est le suivant.
il y a deux groupes de mots, et j'ai besoin de savoir si une chaîne en a un ( ou plus) mot du groupe A alors qu'il a également un mot du groupe B. Comme ça.
if 'nice' in t_string_A and 'no' in t_string_A:
return 1
t_string_A a 'car' de Group_A, alors que rien de Group_B, donc il doit revenir ... Je ne sais pas, disons 0 tandis que t_string_B a 'car' de Group_A, et 'no' de Group_B, il devrait donc renvoyer 1
En fait, je faisais ce travail d'une manière un peu ... primitive. Comme un tas d'ensembles de codes comme
Group_A = ['nice','car','by','shop'] Group_B = ['no','thing','great'] t_string_A = 'there is a car over there' t_string_B = 'no one is in a car'
Mais comme vous le savez, à mesure que la longueur du groupe A ou B augmente, je devrais créer trop d'ensembles de ces ensembles. Et ce n'est certainement pas efficace.
J'apprécie votre aide et votre attention: D Merci d'avance!
5 Réponses :
Oh, il devrait également renvoyer 0: D Mais je pense que votre réponse a déjà résolu mon problème haha. Je l'appliquerai bientôt dans mon code!
Qu'est-ce que l'opérateur & qui est appliqué entre une liste et un ensemble? Jamais vu ça!
@DeveshKumarSingh & est identique à self.intersection (autre) . le lien vers la doc l'explique.
bonne solution, mais je pense que nous n'avons besoin que d'un seul mot pour chaque groupe pour obtenir le même résultat que celui-ci, donc pas besoin de faire cette opération coûteuse. un mot suffit, pour plus vite.
Zut! Merci pour la friandise @hiroprotagonist, j'ai appris quelque chose de nouveau aujourd'hui :)
@hiroprotagonist c'est efficace. mais je dis que pour le même résultat, nous n'avons besoin que d'un seul mot de chaque groupe. pour l'ensemble, c'est une opération coûteuse c'est tout.
@prashantrana a ajouté une variante. cela devrait répondre à vos préoccupations, non?
Ahhh si proche! T_T En fait, je travaille en coréen. Et on dirait que la grammaire coréenne a un problème avec split () ... il y a un mot 'Noun 입니다'. mais split () n'identifie que '입니다' seulement donc ... tout 입니다 attaché avec Noun n'est pas classé comme 입니다.
En terme anglais, hmm ... j'ai besoin de cocher 'chose' y compris 'quelque chose' 'n'importe quoi' etc. ... hmm ....
@hiroprotagonist c'est ça, j'ai aussi posté une solution, ce que je voulais dire
Cela peut être résolu efficacement sous forme de variations de l ' algorithme Aho Corasick a > C'est un algorithme de correspondance de dictionnaire efficace qui localise les modèles dans le texte simultanément dans Vous voudrez peut-être exécuter deux machines à états distinctes simultanément, et vous devrez les modifier donc ils se terminent au premier match. J'ai essayé les modifications, en commençant par cette implémentation python et de l'utiliser Cela affiche O (p + q + r) , avec p = longueur des modèles, q = longueur du texte, r = longueur des correspondances renvoyées. 'there is a car over there' - False
'no one is in a car' - True
patterns_a = ['nice','car','by','shop']
patterns_b = ['no','thing','great']
matcher = all_any_matcher(patterns_a, patterns_b)
text_1 = 'there is a car over there'
text_2 = 'no one is in a car'
for text in (text_1, text_2):
print '%r - %s' % (text, matcher(text))
class AhoNode(object):
def __init__(self):
self.goto = {}
self.is_match = False
self.fail = None
def aho_create_forest(patterns):
root = AhoNode()
for path in patterns:
node = root
for symbol in path:
node = node.goto.setdefault(symbol, AhoNode())
node.is_match = True
return root
def aho_create_statemachine(patterns):
root = aho_create_forest(patterns)
queue = []
for node in root.goto.itervalues():
queue.append(node)
node.fail = root
while queue:
rnode = queue.pop(0)
for key, unode in rnode.goto.iteritems():
queue.append(unode)
fnode = rnode.fail
while fnode is not None and key not in fnode.goto:
fnode = fnode.fail
unode.fail = fnode.goto[key] if fnode else root
unode.is_match = unode.is_match or unode.fail.is_match
return root
def aho_any_match(s, root):
node = root
for i, c in enumerate(s):
while node is not None and c not in node.goto:
node = node.fail
if node is None:
node = root
continue
node = node.goto[c]
if node.out:
return True
return False
def all_any_matcher(*pattern_lists):
''' Returns an efficient matcher function that takes a string
and returns True if at least one pattern from each pattern list
is found in it.
'''
machines = [aho_create_statemachine(patterns) for patterns in pattern_lists]
def matcher(text):
return all(aho_any_match(text, m) for m in machines)
return matcher
Ah ça sonne bien! Mais je pense que c'est bien au-dessus de mes capacités xD Merci de votre attention! C'est vraiment intéressant d'exécuter plusieurs machines à états simultanément. Cela aiderait beaucoup mes autres problèmes.
@JeongInKim n'abandonne pas l'espoir. Si vous effectuez une petite recherche sur le Web, vous constaterez qu'il existe des solutions très similaires à ce problème avec lesquelles vous pourrez peut-être commencer. En fait, même exécuter la version non modifiée (qui trouve toutes les correspondances, exécute deux fois) a le potentiel d'être plusieurs fois plus rapide que ce que vous obtiendrez autrement. S'arrêter sur le premier match pourrait être un projet intéressant à entreprendre
ceci est une réponse lien uniquement - veuillez modifiez votre réponse pour qu'elle soit autonome même si le lien ne fonctionne plus.
@JeongInKim a ajouté une implémentation. C'est python2.7, mais seulement à cause de la parenthèse manquante print et de la déclaration implicite de objet . Vous pouvez également renvoyer la partie correspondante assez facilement - voir l'implémentation d'origine pour les parties que j'ai supprimées
Vous pouvez parcourir les mots et voir si l'un d'entre eux est dans la chaîne:
from typing import List
def has_word(string: str, words: List[str]) -> bool:
for word in words:
if word in string:
return True
return False
Cette fonction peut être modifiée facilement pour avoir has_all_words aussi.
Vous pouvez utiliser itertools.product pour générer tous paires de mots possibles des groupes de don. Vous parcourez ensuite la liste des chaînes, et si une paire est présente dans la chaîne, le résultat est True, sinon le résultat est False.
Group_A = ['thing'] Group_B = ['car'] strings = ['there is a thing in a car', 'Nothing is in a car','Something happens to my car']
Le résultat ressemblera alors à
[True, True, False, False, True]
En plus pour les entrées ci-dessous
import itertools as it
Group_A = ['ì ë', 'ì í¬ë', 'ì°ë¦¬ë']
Group_B = ['ì
ëë¤','ë¼ê³ í©ëë¤']
strings = [ 'ì ë íìì
ëë¤.', 'ì í¬ë íì¬ìë¤ ì
ëë¤.' , 'ì´ ê²ì´ íì¤ ì
ëë¤.', 'ì°ë¦¬ë ë°°ê³ íì.' , 'ì°ë¦¬ë ë°´ëì¤í¸ë¼ê³ í©ëë¤.']
#Get all possible combinations of words from the group
z = list(it.product(Group_A, Group_B))
results = []
#Run through the list of string
for s in strings:
flag = False
for item in z:
#If the word is present in the string, flag is True
if item[0] in s and item[1] in s:
flag = True
break
#Append result to results string
results.append(flag)
print(results)
Les valeurs seront [True, True, True]
Merci Devesh. Mais j'ai trouvé un problème avec split () car j'utilise en fait le coréen. Cela devrait ressembler à ... Group_A = ['thing'] Group_B = ['car'] string_A = 'il y a quelque chose dans une voiture' string_B = 'Il n'y a rien dans une voiture' string_C = 'Quelque chose arrive à ma voiture' Si j'utilise split (), comme vous le savez, rien ou quelque chose dans string_B et C n'est pas classé comme 'chose' dans Group_A. Existe-t-il un autre moyen de vérifier le mot dans une phrase entière? Je veux que string_A, B, C renvoie True: D
Mais devrait-il y avoir un Group_C pour string_C ? Ou avons-nous une correspondance entre les groupes et les chaînes? Comment savoir lequel des Group_A et Group_B correspondra à String_C @JeongInKim?
Oh. J'aurais dû effacer cela. Group_A et Group_B sont juste pour les références et les chaînes sont dans une boucle. Je veux donc vérifier toutes les chaînes d'une boucle respectivement, si elles ont un mot de Group_A et d'autres mots dans un Group_B simultanément.
s'ils ont un mot de Group_A et d'autres mots dans un Group_B simultanément , qu'est-ce que cela signifie? Toutes les chaînes de la boucle doivent avoir des mots du groupe? Ou les chaînes sont-elles sélectionnées par paires, puis comparées à des groupes et seulement si chaque paire remplissait la condition pour que Group_A soit dans StringX et Group_B soit dans StringY pour une paire (StringX, StringY)?
Une chaîne est choisie par une boucle, donc rien à voir avec des paires (j'ai montré deux chaînes pour montrer quelques exemples de True et False). Et pour chaque chaîne choisie, je devrais vérifier s'ils ont un mot de Group_A et l'autre mot de Group_B en même temps. Je suis désolé pour les confusions.
Ok, permettez-moi d'ajouter à ma réponse! La réponse acceptée gère-t-elle ce scénario @JeongInKim
Merci Devesh. En fait non. Mais je n'étais pas clair sur les trucs coréens, et en fait il gère Enlgish, alors je l'ai choisi comme réponse. Mais je suis prêt à changer mon acceptation ou à poser une nouvelle question si vous pouvez m'aider ici
Pouvez-vous partager une partie de votre texte coréen ici? Permettez-moi de m'y attarder, également fractionné sur des espaces, votre texte coréen n'a-t-il pas d'espaces entre les mots?
Corrigez-moi aussi si je me trompe mais pour Group_A = ['thing'] et Group_B = ['car'] et strings = ['il y a une chose dans une voiture »,« Il n'y a rien dans une voiture »,« Quelque chose arrive à ma voiture »] , la réponse sera Vrai, Faux, Faux ? Puisque seul il y a une chose dans une voiture a chose et voiture dans la phrase? Aussi pourquoi avez-vous besoin de deux groupes, lorsque les deux groupes enregistrent la même chaîne? Pourquoi ne pas avoir un groupe appelé ['thing', 'car'] ?
Sûr. J'apprécie vraiment votre passion pour m'aider! les chaînes doivent renvoyer True True True, car il a également quelque chose dans Nothing et Something. C'est pourquoi j'ai un problème avec split () Essayons ceci en coréen Ref_A = ['저는', '저희 는', '우리 는'] Ref_B = ['입니다', '라고 합니다',] ex_A = '저는 학생 입니다.' ex_B = '저희 는 회사원 들 입니다.' ex_C = '이 것이 현실 입니다.' ex_D = '우리 는 배고파요.' ex_E = '우리 는 밴 디스트 라고 합니다.' Le retour devrait être 'T, T, F, F, T'!
Aah maintenant je comprends, vous voulez vérifier une partie des mots aussi, et est-ce sensible à la casse ou à la casse? Pas sûr du cas en coréen cependant
Les groupes seront-ils également de taille inégale comme dans l'exemple ici, où Ref_A est de taille 3 et Ref_B est de taille 2?
Oui ! Et insensible à la casse, car il n'y a pas de mots majuscules en coréen. De plus, ce sera plus utile pour moi si je l'essaie en anglais: D Et oui, ces groupes sont très probablement de tailles différentes. (Alors peut-être avoir un problème avec les zips? Haha ... Idk). Ainsi, dans les exemples, la chaîne doit être vérifiée avec 3 * 2 ensembles de combinaisons.
Compris, et si une combinaison est contenue dans la chaîne, le résultat devrait être vrai?
Exactement: D !!
D'accord, j'ai mis à jour ma réponse! J'ai utilisé votre exemple, et la réponse que j'obtiens est ce que vous attendiez aussi @JeongInKim
Ahhh Vous êtes une telle vie savour Devesh! Ça marche! J'apprécie vraiment cela! Maintenant, je peux ajouter plus de mots à la référence sans avoir à ajouter un tas de codes en double haha. Je peux aussi apprendre de votre code et l'appliquer à d'autres contextes! Sincèrement, merci!
Je suggérerais d'être plus verbeux et précis la prochaine fois que vous poserez une question :)
Chose sûre! Je vais! Je suis vraiment désolé de t'avoir tellement retenu.
@Cireo Merci Cireo! Ce serait aussi mes préoccupations, mais chaque groupe ne contient que moins de ... 20? Donc c'est bon pour mon code! Mais j'étudie aussi d'autres codes grâce aux autres!
Group_A = ['nice','car','by','shop']
Group_B = ['no','thing','great']
from collections import defaultdict
group_a=defaultdict(int)
group_b=defaultdict(int)
for i in Group_A:
group_a[i]=1
for i in Group_B:
group_b[i]=1
t_string_A = 'there is a car over there'
t_string_B = 'no one is in a car'
def fun2(string):
l=[]
past=0
for i in range(len(string)):
if string[i]==' ':
if string[past:i]!='':
l.append(string[past:i])
past=i+1
return l
def fun(string,dic):
for i in fun2(string):
# for i in string.split():
try:
if dic[i]:
return 1
except:
pass
return 0
if fun(t_string_A,group_a)==fun(t_string_B,group_b):
print(1)
else:
print(0)
Merci pour votre réponse Rana! Mais il s'avère que j'ai besoin de quelque chose sans split () ... T_T ;; Si vous avez des réponses en vérifiant un mot «chose», y compris «n'importe quoi» et «quelque chose», etc. Ce sera d'une grande aide!
La solution @JeongInKim mise à jour, selon vos besoins, n'a pas utilisé split () mais a écrit une fonction qui fait la même chose.
Si je comprends bien, les mots aux mêmes index dans
GroupAetGroupBsont en cours de vérification par rapport àt_string_Aett_string_Brespectivement?Consultez cette discussion: stackoverflow.com / questions / 11015320 /… Vous pouvez faire un essai pour A et un pour B et faire un test d'adhésion.
@DeveshKumarSingh Oh dans les vrais codes, c'est dans une boucle alors, ouais. I il devrait être vérifié respectivement: D
D'accord, vérifiez si ma réponse vous aide, puis @JeongInKim et votez / acceptez si cela vous aide :)