Пересечение списка и первого элемента списка списков


У меня есть два списка:

wordlist =  ['A', 'Aani', 'Aaron', 'Aaronic',
             'Aaronical', 'Aaronite', 'Aaronitic',
             'Aaru', 'Ab', 'Ababdeh']

И

wordlist_compound = [['A','0'], ['Aaronic','1'], ['Key','2'],
                     ['Aaronical','3'], ['Aaronite','4'], ['Yes','5']]

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

[['A','0'], ['Aaronic','1'], ['Aaronical','3'], ['Aaronite','4']]

Мой текущий код выглядит так:

wordlist_final = []
for index, word in enumerate(wordlist):
    for word_comp in wordlist_compound:
        if word[index] == wordlist_compound[index][0]:
            wordlist_final.append(wordlist_compound[index])

Но я получаю "string index out of range error"

4 3

4 ответа:

Ваш вывод легко достигается с помощью понимания списка:

wl=['A', 'Aani', 'Aaron', 'Aaronic', 'Aaronical', 'Aaronite', 'Aaronitic', 'Aaru', 'Ab', 'Ababdeh']
wlc=[['A','0'], ['Aaronic','1'], ['Key','2'], ['Aaronical','3'], ['Aaronite','4'], ['Yes','5']]

print [[word, i] for word,i in wlc if word in wl]    
# [['A', '0'], ['Aaronic', '1'], ['Aaronical', '3'], ['Aaronite', '4']]

Альтернативный LC:

print [li for li in wlc if li[0] in wl]   

Если вам нужна циклическая структура:

wlf = []
for word, i in wlc:
    if word in wl:
        wlf.append([word,i])

print wlf       
# [['A', '0'], ['Aaronic', '1'], ['Aaronical', '3'], ['Aaronite', '4']]

Последовательности Pythonобычно не нужно перечислять, чтобы просто иметь дело с объектами в последовательности. Вы обычно должны использовать enumerate только в том случае, если в индексе или порядке есть что-то, что является "данными" в дополнение к самой последовательности.

Здесь вы берете каждый элемент в wordlist_compound и проверка принадлежности слова в wordlist. Нет необходимости в перечислении. Вы также значительно упростите задачу, если вы перевернете петли; петля над wordlist_compound, а не петля над wordlist во внешнем цикле, как у вас есть. Ваш выход-это фильтр элементов в wordlist_compound; что, конечно, означает, что вы можете использовать filter тоже:

print filter(lambda li: li[0] in wl, wlc)
# [['A', '0'], ['Aaronic', '1'], ['Aaronical', '3'], ['Aaronite', '4']]

Ура.

Проблема в том, что len(wordlist) > len(wordlist_compound), поэтому использование index из wordlist для индексации wordlist_compound даст индекс из связанных ошибок.

Также, как упоминал @ ага, должно быть if word == wordlist_compound[index][0].

if word[index] == wordlist_compound[index][0]:

Я считаю, что это должно быть

if word == wordlist_compound[index][0]:

Вы получаете это исключение для элемента 'Aaru': его индекс равен 7, а 'Aaru'[7] не существует.

Но это наблюдение не поможет вам, потому что ваш цикл содержит некоторые логические ошибки. Я бы переписал его так:
for inner_list in wordlist_compound: 
    if inner_list[0] in wordlist: 
        wordlist_final.append(inner_list) 

Или используйте понимание списка, как показал dawg.

В зависимости от размера двух коллекций, я бы, вероятно, сделал это так:

word_numbers = dict(wordlist_compound)
wordlist_final = [(word, word_numbers[word]) for word in wordlist if word in word_numbers]

Если вы не заботитесь о порядке результата (или если оба списка находятся в одном и том же порядке, в данном случае в алфавитном порядке), то вы можете вместо этого сделать:

words = set(wordlist)
wordlist_final = [p for p in wordlist_compound if p[0] in words]

Это был бы лучший вариант, если wordlist_compound, вероятно, будет значительно больше, чем wordlist.

Я только что заметил, что в обоих случаях я вернул список кортежей, тогда как у вас есть список списков. Вы можете исправить это, если это необходимо. меняя () на [] в моем первом блоке кода, или меняя p for p на list(p) for p во втором.