Получить индексы последовательностей слов в текстах, представленных в виде списка слов

#python #string #list #find

Вопрос:

Дан абзац, представленный в виде списка слов:

 context = ['Katie', 'Joplin', 'is', 'an', 'American', 'sitcom', 'created', 'by', 'Tom', 'Seeley', 'and', 'Norm', 'Gunzenhauser', '.', 'The', 'sitcom', 'received', 'positive', 'reviews', 'thanks', 'to', 'the', 'brilliance', 'of', 'Tom', 'Seeley', '.']
 

И список целевых строк из нескольких слов:

 target = ['sitcom created', 'Tom Seeley']
 

Как получить индексы целевых объектов с несколькими словами?

В этом случае ответ должен быть:

 [[5, 6], [8, 9], [24, 25]]
 

Ответ №1:

Если context содержит только отдельные слова (без пробелов), вы можете объединить контекст в одну строку, а затем использовать str.index :

 target = ["sitcom created", "Tom Seeley"]

out, joined = [], " ".join(context)
for t in target:
    try:
        idx = joined.index(t)
        cnt = joined[:idx].count(" ")
        out.append([cnt, cnt   t.count(" ")])
    except:
        continue

print(out)
 

С принтами:

 [[5, 6], [8, 9]]
 

ИЗМЕНИТЬ: Для нескольких случаев:

 target = ["sitcom created", "Tom Seeley"]

out, joined = [], " ".join(context)
for t in target:
    idx = 0
    while True:
        try:
            idx_new = joined[idx:].index(t)
            cnt = joined[: idx   idx_new].count(" ")
            out.append([cnt, cnt   t.count(" ")])
            idx  = idx_new   len(t)
        except:
            break

print(out)
 

С принтами:

 [[5, 6], [8, 9], [24, 25]]
 

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

1. Это хорошо работает в данном контексте, но дает только первое вхождение. Если бы контекст повторил Том Сили, код должен получить все вхождения. Я изменил контекст, чтобы он содержал это.

Ответ №2:

Numpy выполняет операции на языке Си, так что это должен быть один из самых странных способов решения it….lol….as обычно мы используем его для численных вычислений, преобразуем массивы в numpy, а затем сравниваем их с помощью широковещания. Это предполагает, что цели из нескольких слов присутствуют в массиве

 A = np.array(context)
B = np.array(['sitcom created'.split(), 'Tom Seeley'.split()])
np.argmax(A == B[..., None], axis=2)
# [[5, 6], [8, 9]]
 
 y = np.where(A == B[..., None])
pre_x, pre_y=(None, None)
l = []
for x, y, z in np.vstack(y).T:
    if x == pre_x and y == pre_y:
        l[-1][-1].append(z)
    elif x == pre_x and y != pre_y:
        l[-1].append([z])
    else:
        l.append([[z]])
    pre_x, pre_y = x, y
# [[[5, 15], [6]], [[8, 24], [9, 25]]]

from itertools import product
sum(map(list, map(lambda x: product(*x), l)), [])
# [(5, 6), (15, 6), (8, 9), (8, 25), (24, 9), (24, 25)]