Python: В списке кортежей получить ключ предыдущего кортежа, когда будет найдено значение следующего кортежа? - PullRequest
1 голос
/ 05 июля 2019

У меня есть список кортежей:

sentenceParts = [('there', 'EX'), ('is', 'VBZ'), ('a', 'DT'), ('huge', 'JJ'), ('shaggy', 'NN'), ('dog', 'NN'), ('in', 'IN'), ('the', 'DT'), ('yard', 'NN')]

Я хочу иметь функцию, посредством которой, если, например, я знаю, мне нужно найти значение 'IN' (ключ которого в данном случае'in'), функция вернет ключ ПРЕДЫДУЩИЙ кортежей (в данном примере 'собака'), а также числовой индекс ключа этого кортежа (в этом случае я считаю, что это будет 5 [0])

В настоящее время я получаю значение для поиска ('in') из этой строки:

wordIndex = next((word for word, value in sentenceParts if value == "IN"), None)

Эта строка возвращает ключ 'in', правильно.Мне нужен аналогичный способ для получения нужного мне результата ('dog', 5 [0] prehaps).Я пробовал возиться с различными версиямиать на фразеParts.index (wordIndex), но я определенно не правильно его использую.Я нашел по крайней мере три разных способа заставить код возвращать «in» мне и несколько десятков способов получить ValueError или AttributeError ... но пока не повезло, когда я обернул голову, возвращая что-то вроде 'dog', 5 [0]

Если бы мне пришлось поместить его в псевдокод, это было бы:

wordIndex = next((PREVIOUS word, INDEX, for word, value in sentenceParts if value == "IN"), None)

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

Ответы [ 4 ]

2 голосов
/ 05 июля 2019

Используйте zip и enumerate над заархивированными списками:

def get_previous_item(lst, search_item):
    for i, (x, y) in enumerate(zip(lst, lst[1:])):
        if y[1] == search_item:
            return i, x[0]

Использование

>>> get_previous_item(sentenceParts, 'IN')
(5, 'dog')
1 голос
/ 05 июля 2019

Идея состоит в том, чтобы перебирать биграммы, а не отдельные слова, поэтому у вас всегда есть предыдущее слово в качестве доступного контекста:

words = [('there', 'EX'), ('is', 'VBZ'), ('a', 'DT'), ('huge', 'JJ'), ('shaggy', 'NN'), ('dog', 'NN'), ('in', 'IN'), ('the', 'DT'), ('yard', 'NN')]
next(((token1, i)
      for i, ((token1, pos1), (token2, pos2))
      in enumerate(zip(words, words[1:]))
      if pos2 == 'IN'
     ), None)
# => ('dog', 5)
0 голосов
/ 05 июля 2019

Что-то более простое, которое возвращает None, если предыдущий ключ не может быть найден (если искомый ключ не найден или находится на первой позиции):

def find_prev( lst, key ):
    try:
        i = [x[1] for x in lst].index(key)
        if i > 0:
            return (i-1,lst[i-1][0])
    except:
        pass
    return None
0 голосов
/ 05 июля 2019
[(sentenceParts[i-1][0], i-1) for i, (w,t) in enumerate(sentenceParts) if t == 'IN' and i >0]


[('dog', 5)]
...