1
votes

Comment rechercher efficacement une liste de chaînes dans une autre liste de chaînes en utilisant Python?

J'ai deux listes de noms (chaînes) qui ressemblent à ceci:

match = next((x for x in executives if x in str), False)
match

J'ai besoin de trouver où ces noms apparaissent dans une liste de chaînes qui ressemble à ceci:

if any(x in str for x in executives):
    print('yes')

La raison pour laquelle je dois faire cela est que je puisse concaténer les chaînes de conversation ensemble (qui sont séparées par les noms). Comment pourrais-je procéder efficacement?

J'ai regardé des questions similaires et essayé les solutions en vain, comme ceci:

str = ['Justin Post - Bank of America',
 "Great. Thank you for taking my question. I guess the big one is the deceleration in unit growth or online stores.", 
"I know it's a tough 3Q comp, but could you comment a little bit about that?",
 'Brian Olsavsky - Amazon.com',
 "Thank you, Justin. Yeah, let me just remind you a couple of things from last year.", 
"We had two reactions on our Super Saver Shipping threshold in the first half." ,
 "I'll just remind you that the units  those do not count",
 "In-stock is very strong, especially as we head into the holiday period.",
 'Dave Fildes - Amazon.com',
"And, Justin, this is Dave. Just to add on to that. You mentioned the online stores.

et ceci ...

XXX


6 commentaires

Pourquoi avez-vous deux listes de noms en premier lieu et votre code ne parcourt qu'une seule d'entre elles?


Il s'agit d'une transcription de questions et réponses, les noms sont donc le moyen le plus simple de diviser les questions et les réponses. Les noms me disent également qui pose la question (analystes) et qui y répond (dirigeants). Je pourrais également mettre les noms dans un dictionnaire si cela rend l'opération plus facile / plus efficace.


Quelle est la sortie souhaitée?


Vérifiez cette réponse, j'espère que cela vous aidera. stackoverflow.com/questions/4843158/...


En fin de compte, le résultat souhaité serait une nouvelle liste de chaînes qui ressemblerait à ceci: str = ['Question Asker', 'blah blah blah. bla bla bla. »,« Répondeur »,« bla bla bla bla bla bla. bla bla bla. ',' Question Asker ',' bla bla. bla bla. »,« Répondeur »,« bla bla »]. La principale distinction est qu'il n'y a qu'une seule chaîne après chaque nom plutôt que plusieurs.


@HamzaKhan. Merci! Je pense que cela devrait aider. Pour une raison quelconque, cette réponse n'est jamais venue dans la myriade de recherches Google que j'ai faites.


3 Réponses :


1
votes

Je ne sais pas si c'est ce que vous recherchez:

executives = ['Brian Olsavsky', 'Some Guy', 'Some Lady']
text = ['Justin Post - Bank of America',
 "Great. Thank you for taking my question. I guess the big one is the deceleration in unit growth or online stores.", 
"I know it's a tough 3Q comp, but could you comment a little bit about that?",
 'Brian Olsavsky - Amazon.com',
 "Thank you, Justin. Yeah, let me just remind you a couple of things from last year.", 
"We had two reactions on our Super Saver Shipping threshold in the first half." ,
 "I'll just remind you that the units  those do not count",
 "In-stock is very strong, especially as we head into the holiday period.",
 'Dave Fildes - Amazon.com',
"And, Justin, this is Dave. Just to add on to that. You mentioned the online stores."]

result = [s for s in text if any(ex in s for ex in executives)]
print(result)

résultat: ['Brian Olsavsky - Amazon.com']


2 commentaires

C'est parfait! Merci! Cela a révélé une faille dans mon raisonnement en ce que certains des noms apparaissent dans les questions, mais cela résout parfaitement mon problème de trouver les noms dans le texte. Devrait être en mesure d'apporter de légères modifications pour résoudre le nouveau problème assez facilement.


@RagnarLothbrok, je suis heureux que cela ait fonctionné pour vous. Veuillez revoir le code, je le modifie légèrement avec la même réponse.



1
votes
[['Brian Olsavsky', 3, 0], ['Justin', 0, 0], ['Justin', 4, 11], ['Justin', 9, 5]]

2 commentaires

C'est également très utile. Merci! Cela pourrait aider avec certaines des opérations que je dois effectuer.


@RagnarLothbrok Je suis heureux d'avoir pu vous aider



1
votes

TLDR

Cette réponse se concentre sur l ' efficacité . Utilisez les autres réponses si ce n'est pas un problème clé. Si tel est le cas, créez un dict à partir du corpus dans lequel vous recherchez, puis utilisez ce dict pour trouver ce que vous recherchez.


plt.plot(number_of_bigrams_we_search_for, bruteforcetime,label='linear')
plt.plot(number_of_bigrams_we_search_for, logtime,label='log')
plt.yscale('log')
plt.legend()
plt.xlabel('Number of bigrams searched')
plt.ylabel('Time elapsed (sec)')

Créer un corpus d'exemple

Commençons par créer une liste de chaînes dans lesquelles nous allons chercher.

Créer des mots aléatoires, c'est-à-dire séquence aléatoire de caractères, avec une longueur tirée d'une distribution de Poisson , avec cette fonction: p>

plt.plot(number_of_bigrams_we_search_for, bruteforcetime,label='linear')
plt.plot(number_of_bigrams_we_search_for, logtime,label='log')
plt.legend()
plt.xlabel('Number of bigrams searched')
plt.ylabel('Time elapsed (sec)')

( lam_word étant le paramètre du Distribution de Poisson .)

Créons nombre_de_sentences phrases de longueur variable à partir de ces mots (par phrase Je veux dire la liste des mots générés aléatoirement séparés par des espaces).

La longueur des phrases peut également être tirée d'un Distribution de Poisson .

logtime=[]
for number_of_bigrams in number_of_bigrams_we_search_for:
    
    bigrams = [bigramgen(2,1) for _ in range(number_of_bigrams)]
    
    start_time=time.time()
    
    worddict={word:set() for sentence in sentences for word in sentence.split(' ')}

    for sentencei, sentence in enumerate(sentences):
        for wordi, word in enumerate(sentence.split(' ')):
            worddict[word].add(sentencei)

    for bigram in bigrams:
        reslist=[]
        setlist = [worddict[gram] for gram in bigram.split(' ')]
        intersection = set.intersection(*setlist)
        for candidate in intersection:
            if bigram in sentences[candidate]:
                reslist.append([bigram, candidate])

    end_time=time.time()
    
    logtime.append(end_time-start_time)

phrases [0] va maintenant commencer comme ceci:

tptt lxnwf iem fedg wbfdq qaa aqrys szwx zkmukc ...

Créons également des noms, que nous rechercherons. Que ces noms soient des bigrammes . Le prénom (c'est-à-dire le premier élément du bigramme) sera composé de n caractères, le nom (deuxième élément du bigramme) sera m de long, et il sera composé de caractères aléatoires:

for bigram in bigrams:
    reslist=[]
    setlist = [worddict[gram] for gram in target.split(' ')]
    intersection = set.intersection(*setlist)
    for candidate in intersection:
        if bigram in sentences[candidate]:
            reslist.append([bigram, candidate])

La tâche

Disons que nous voulons trouver phrases où apparaissent des bigrammes tels que ab c . Nous ne voulons pas trouver dab c ou ab cd , uniquement là où ab c est seul.

Pour tester à quelle vitesse une méthode est, trouvons un nombre toujours croissant de bigrammes et mesurons le temps écoulé. Le nombre de bigrammes que nous recherchons peut être, par exemple:

for sentencei, sentence in enumerate(sentences):
    for wordi, word in enumerate(sentence.split(' ')):
        worddict[word].add(sentencei)
  • Méthode de la force brute

Il suffit de parcourir chaque bigramme, de parcourir chaque phrase, d'utiliser dans pour trouver des correspondances. Pendant ce temps, mesurez le temps écoulé avec time.time().

worddict={word:set() for sentence in sentences for word in sentence.split(' ')}

bruteforcetime contiendra le nombre de secondes nécessaires pour trouver 10, 30, 50 ... bigrammes.

Attention: cela peut prendre longtemps pour un grand nombre de bigrammes.

  • La méthode triez vos contenus pour les rendre plus rapides

Créons un ensemble vide pour chaque mot apparaissant dans l'une des phrases (en utilisant compréhension de dict ) :

bruteforcetime=[]
for number_of_bigrams in number_of_bigrams_we_search_for:
    bigrams = [bigramgen(2,1) for _ in range(number_of_bigrams)]
    start = time.time()
    for bigram in bigrams:
        #the core of the brute force method starts here
        reslist=[]
        for sentencei, sentence in enumerate(sentences):
            if ' '+bigram+' ' in sentence:
                reslist.append([bigram,sentencei])
        #and ends here
    end = time.time()
    bruteforcetime.append(end-start)

À chacun de ces ensembles, ajoutez l ' index de chaque mot dans lequel il apparaît:

number_of_bigrams_we_search_for = [10,30,50,100,300,500,1000,3000,5000,10000]

1 commentaires

Vous pourriez être encore plus rapide si vous considérez les réponses (j'espère arriver) à cette question: stackoverflow.com/questions/63093605/...