Если вы не разрешено импортировать что-либо, то ловкий reduce
операцию вместе с slicing
и zip
(все из них являются Python встроенные модули, не требующие импорта) может быть очень компактный способ сделать это:
EDIT После того, как он указал мне, что я неправильно понял проблему, исправил ее, изменив инструкцию zip()
.
# the string - split it immediately into a list of words
# (some words deleted to make it smaller)
words = "dimension implies direction implies the more and the less".split()
# There is a **lot** going on in this line of code, explanation below.
result = reduce(lambda acc, kv: acc.setdefault(kv[0], []).append(kv[1]) or acc,
zip(words[1:], words[:-1]), {})
# this was the previous - incorrect - zip()
# zip(words[1::2], words[0::2]), {})
и вывод результата (также отредактирован)
print result
{'and': ['more'], 'direction': ['implies'], 'implies': ['dimension',
'direction', 'measurement'], 'less': ['the'], 'measurement':['implies'],
'the': ['implies', 'and'], 'more': ['the']}
Для полноты, старый, ошибочный, результат:
print result
{'the': ['and'], 'implies': ['dimension', 'direction', 'measurement'], 'more': ['the']}
Немного объяснения
После разделения строки на список слов мы можем индексировать отдельные слова как words[i]
.
отредактировал К описанию проблемы ключи ключа, полученные в результате, - это слова, следующие за словом, значение которого является первым словом. Поэтому мы должны преобразовать список слов в список комбинаций каждого слова со следующим словом. Таким образом, список key
будет представлять собой список [слова [1], слова [2], слова [3], ....] и values
, которые идут с такими словами: [слова [0], слова [1 ], слова [2], ..., слова [n-1]].
Использование Python slicing
: keys = words[1:]
и values = words[:-1]
Теперь нам нужно создать dict
этих ключей и значений, агрегирование значений в list
, если же ключ происходит несколько раз.
dict
имеет метод .setdefault(key, value)
который будет инициализировать значение key
«с до value
, если key
не в dict
еще, в противном случае возвращает значение, как это в настоящее время. По умолчанию-инициализируя все значения пустым list
([]
), мы можем вслепую называть .append(...)
. Это то, что делает эту часть кода:
acc.setdefault(key, []).append(value)
Тогда есть reduce
. Операция уменьшения уменьшает (...) список значений в один. В этом случае мы уменьшим список (key, value)
кортежей в dict
, где мы скопировали все значения в их соответствующий ключ.
reduce
принимает функцию сокращения обратного вызова и начальный элемент. Исходным элементом здесь является пустой dict {}
- мы будем заполнять это, когда мы идем.
Функция уменьшения обратного вызова вызывается многократно с двумя аргументами, аккумулятором и следующим элементом для добавления к накоплению. Функция должна вернуть новый аккумулятор.
В этом коде шаг восстановления в основном является добавлением значения элемента в список значений для ключа элемента. (См. Выше - вот что делает .setdefault().append()
).
Все что нам нужно - это получить список (key, value)
кортежей, которые нам нужно обработать. Вот где появится встроенный zip
. zip
берет два списка и возвращает список кортежей соответствующих элементов.
Таким образом:
zip(words[1:], words[:-1])
производит именно то, что мы хотим: список всех (key, value)
кортежей.
Наконец, поскольку функция уменьшения должна возвращать новый аккумулятор, мы должны сыграть трюк. list.append(...)
возвращает None
, хотя фактический dict был изменен. Таким образом, мы не можем вернуть это значение в качестве следующего аккумулятора. Таким образом, после этого мы добавляем конструкцию or acc
.
Поскольку левая сторона логической or
всегда имеет значение None
, которое логически False
в Python, правая рука всегда «оценивается» - в этом случае (модифицированный) Сыроватского себя. Таким образом, итоговый результат or
оценивает сам модифицированный dict, что и нужно вернуть.
мне было интересно, если добавление: 'если я == 0: stenence_dict [words_list [я]] = ''' бы помочь получить пустое значение для первого индекса – Nume
Поскольку вы назначая 'sentence_dict [words_list [I ]] = words_list [i-1] 'не добавляя существующее значение. Вы должны проверить для 'i == 0' для первого слова. – ismailsunni
в качестве примечания: первая петля цикла должна быть заменена прямым контуром над словами –