Функция работает для небольших образцов, но не для больших (Python)

#python #arrays #function #memory-management #nlp

Вопрос:

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

   file_cont = [['man', 'once', 'upon', 'time', 'love',  'princess'], ['python', 'code', 'cool', 'uses', 'java'], ['man', 'help', 'test', 'weird', 'love']] #words I want to measure 'distance' between  dat = [{ind: val for val, ind in enumerate(el)} for el in file_cont]  def myfunc(w1, w2, dist, dat):  arr = []  for x in dat:  i1 = x.get(w1)  i2 = x.get(w2)  if (i1 is not None) and (i2 is not None) and (i2 - i1 lt;= dist ):   arr.append(list(x.keys())[i1:i2 1])  return arr   

Это работает в данном случае,

myfunc(«человек», «Любовь»,4, DAT-файла) возвращает [[‘человек’, ‘как только’, ‘по’, ‘Время’, ‘любить’], [‘человек’, ‘помощь’, ‘тест’, ‘странно’, ‘любить’]] , который является то, что я хочу

Проблема, с которой я сталкиваюсь, заключается в том, что когда я использую гораздо больший набор данных (элементы file_cont становятся тысячами слов), он выдает нечетные результаты

Например, я знаю, что слова «джон» и «снег» появляются вместе по крайней мере в одном экземпляре в одном из элементов file_cont

Когда я выполняю свою функцию(«джон»,»сноу»,6,дата), я получаю:

[[], [], [‘замок’, ‘палата’], [], [], []]

что-то совершенно вырванное из контекста, в нем не упоминается «джон» или «сноу»

В чем здесь проблема и как бы я ее решил исправить?

Комментарии:

1. Мне приходят на ум две вещи: во-первых, вы упомянули, что проблема возникает только при использовании большего набора данных. Как вы используете этот набор данных? Вы читаете текстовый файл и разбиваете его на список? Проблема может быть вызвана тем, как вы читаете свои данные. В противном случае вы упоминаете случай "jon" и. "snow" Возможно, вам следует убедиться, что вы ищете слова без учета регистра, например, используя s.lower() где s находится строка?

2. @bglbrt Я записал слова в нижнем регистре и все еще испытываю ту же проблему

3. @bglbrt это также те же данные из [[‘string1’, ‘string2’], [‘string3’, ‘string4’, ‘string5’]] только длиннее

4. Я добавил ответ, исследующий дальнейшую проблему, которая, как я полагаю, связана с тем фактом, что в ваших новых данных может быть несколько вхождений одних и тех же слов.

5. @bglbrt код работает для более длинных больших списков, но, похоже, все еще не работает для списка длинных списков, т. е. [ [ ‘word1’,…., ‘word1000’], [‘word3’,….. ‘word5000’], [‘word4’,…. ‘word400’]] даже когда слова, между которыми я хочу найти расстояние, находятся в одном списке (к чему я и стремлюсь)

Ответ №1:

Проблема заключается в том, что ваш текст может содержать несколько вхождений одного и того же слова, которые вы обычно наблюдаете с большими выдержками.

Вот минимальный рабочий пример, показывающий, как функция может выйти из строя:

 new_file = [['man', 'once', 'man', 'time', 'love', 'once']] data = [{ind: val for val, ind in enumerate(el)} for el in new_file]  def myfunc(w1, w2, dist, dat):  arr = []  for x in dat:  i1 = x.get(w1)  i2 = x.get(w2)  if (i1 is not None) and (i2 is not None) and (i2 - i1 lt;= dist ):   arr.append(list(x.keys())[i1:i2 1])  return arr  myfunc("man", "love", 4, data) # gt; [['time', 'love']]  

Обратите внимание, что здесь ваш словарь будет выглядеть следующим образом:

 # gt; [{'man': 2, 'once': 5, 'time': 3, 'love': 4}]  

Это связано с тем, что при создании словаря каждое новое вхождение слова будет заменять его ключ в словаре новым наблюдаемым (более высоким) индексом. Таким образом, функция myfunc не работает, так как ключи в словаре больше не соответствуют индексам слов в отрывке.


Способ достичь того, что вы хотите сделать, может быть (например):

 data = ['man', 'once', 'upon', 'man', 'time', 'love', 'princess', 'man'] w1 = 'man' w2 = 'love' dist = 3  def new_func(w1, w2, dist, data):   w1_indices = [i for i, x in enumerate(data) if x == w1]  w2_indices = [i for i, x in enumerate(data) if x == w2]   for i in w1_indices:  for j in w2_indices:  if abs(i-j) lt; dist:  print(data[min(i, j):max(i, j) 1])   new_func(w1, w2, dist, data) # gt; ['man', 'time', 'love'] # gt; ['love', 'princess', 'man']  

С помощью списка списков, как в вашем случае, вы можете сделать:

 file_cont = [['man', 'once', 'upon', 'time', 'love', 'princess'], ['python', 'code', 'cool', 'uses', 'java'], ['man', 'help', 'test', 'weird', 'love']]  results = [new_func(w1, w2, dist, x) for x in file_cont] print(results) # gt; ['man', 'once', 'upon', 'time', 'love'] # gt; ['man', 'help', 'test', 'weird', 'love']  

Комментарии:

1. Я полагаю, что в вашем коде есть ошибка : print(a[min(i, j):max(i, j) 1]), должно ли это быть abs?

2. Вы правы — я исправил это, так и должно быть print(data[min(i, j):max(i, j) 1]) .