РЕДАКТИРОВАТЬ: новая версия после обновления проблемы.
Пример данных теперь:
>>> d_filtered_words = {
... '1': ['avoir', 'main'],
... '2': ['main', 'serrer', 'posséder'],
... }
>>> dico_lexique = {
... 'avoir': ('101', '3772', '110'),
... 'avoir>posséder': ('91', '2724', '108'),
... 'serrer': ('175', '936', '252'),
... 'main': ('251', '2166', '49'),
... }
Сначала необходимо обработать dico_lexique
, чтобы удалить детали после >
и сгруппировать значения по главному слову:
>>> values_by_word = {}
>>> for word, values in dico_lexique.items():
... main, *_ = word.split(">")
... values_by_word.setdefault(main, []).append(values)
>>> values_by_word
{'avoir': [('101', '3772', '110'), ('91', '2724', '108')], 'serrer': [('175', '936', '252')], 'main': [('251', '2166', '49')]}
Пояснение:
main, *_ = word.split(">")
хранит все перед необязательным >
и забывает все остальное (см. назначение деструктурирования )
setdefault
создает новый список, связанный с основным словом, если оно не существует, и добавляет значения.
Теперь та же логика, что и ниже:
>>> def merge_values(tuples):
... """Sums columns (with a str->int->str conversion)"""
... return tuple(str(sum(int(v) for v in vs)) for vs in zip(*tuples))
>>> merged_values_by_word = {code:merge_values(tuples) for code, tuples in values_by_word.items()}
>>> merged_values_by_word
{'avoir': ('192', '6496', '218'), 'serrer': ('175', '936', '252'), 'main': ('251', '2166', '49')}
(я переименовал get_values
в merge_values
, но это та же функция.)
Вы можете использовать код ниже с merged_values_by_word
вместо dico_lexique
.
Конец редактирования: старая версия ниже, для записи
Вы смешиваете две проблемы: что делает ваш код (суммирование значений, связанных со словами или семейством слов) и анализ файла или строки.
Некоторый обзор кода
Позвольте мне подвести итог:
* у вас есть dico_lexique
, который отображает слово на три значения (строки, содержащие целые числа)
* у вас есть d_filtered_words
, который отображает код ('15', '44', ...) в список слов.
* вы создаете команду, которая отображает код на [sum of the value1, sum of the value2, sum of the value2]
для каждого слова, которое сопоставлено с кодом и присутствует в dico_lexique
.
Во-первых, если у вас всегда есть три значения, используйте tuple
, а не list
. Я буду использовать этот пользовательский образец:
>>> d_filtered_words = {
... '1': ['avoir', 'main'],
... '2': ['main', 'serrer', 'posséder'],
... }
>>> dico_lexique = {
... 'avoir': ('101', '3772', '110'),
... 'serrer': ('175', '936', '252'),
... 'main': ('251', '2166', '49'),
... # no posséder here
... }
Во-вторых, создайте dict, который отображает код в список из трех значений:
>>> def get_tuples(words):
... """return the tuples of values for every word in dico_lexique"""
... return [dico_lexique[word] for word in words if word in dico_lexique]
>>> tuples_by_code = {code:get_tuples(words) for code, words in d_filtered_words.items()}
>>> tuples_by_code
{'1': [('101', '3772', '110'), ('251', '2166', '49')], '2': [('251', '2166', '49'), ('175', '936', '252')]}
В-третьих, суммируйте значения «по столбцу». Есть простой способ сделать это:
>>> tuples = [(1,2,3), (4,5,6)]
>>> tuple(zip(*tuples))
((1, 4), (2, 5), (3, 6))
>>> tuple(map(sum, zip(*tuples)))
(5, 7, 9)
Функция zip
сгруппирует первый элемент каждого кортежа, затем второй элемент каждого кортежа, затем ...: вы получаете «столбцы» и просто должны их суммировать. В вашем случае:
>>> def get_values(tuples):
... """Sums columns (with a str->int->str conversion)"""
... return tuple(str(sum(int(v) for v in vs)) for vs in zip(*tuples))
>>> values_by_code = {code:get_values(tuples) for code, tuples in tuples_by_code.items()}
>>> values_by_code
{'1': ('352', '5938', '159'), '2': ('426', '3102', '301')}
Ваш вопрос
Теперь ваш вопрос. Представьте, что у меня есть текстовый файл с альтернативными формами:
>>> text = """avoir>posséder
... voilé>dissimulé
... voilé>caché"""
Вы должны проанализировать этот файл и разбить каждую строку на >
, чтобы создать диктовку alternative -> main
:
>>> main_by_alternative = {a: m for line in text.split("\\n") for m, a in [line.split(">")]}
>>> main_by_alternative
{'posséder': 'avoir', 'dissimulé': 'voilé', 'caché': 'voilé'}
Основная идея состоит в том, чтобы разбить строку на символе >
, чтобы получить основную форму и альтернативную форму в списке. for m, a in [line.split(">")]
- это уловка, чтобы иметь m, a = line.split(">")
в понимании слова. Теперь вернемся к get_tuples
:
>>> def get_tuples(words):
... """return the tuples of values for every word in dico_lexique"""
... return [dico_lexique[main_by_alternative.get(word, word)] for word in words if main_by_alternative.get(word, word) in dico_lexique]
Что нового? Посмотрите на: main_by_alternative.get(word, word)
. Он просто получает основную форму, если он выходит, или само слово.
>>> {code:get_tuples(words) for code, words in d_filtered_words.items()}
{'1': [('101', '3772', '110'), ('251', '2166', '49')], '2': [('251', '2166', '49'), ('175', '936', '252'), ('101', '3772', '110')]}
Код 2
теперь сопоставляется с тремя словами: «главный», «serrer», «эвир» (через «posséder»).
Надеюсь, это поможет. Я использовал много толкований / списков, чтобы сделать его коротким, но если вам нужно, не стесняйтесь расширять код в регулярные циклы.