Как перебрать словарь в Python, чья (k, v) пара использует последовательные элементы из списка - PullRequest
0 голосов
/ 04 марта 2019

Я хочу добавить (k,v) пары в словарь weights, где ключ этого словаря равен объекту из списка layers.Конструкция значения такова, что он использует объект l и объект l+1 из этого списка.В настоящее время я делаю это следующим образом:

layers = self.layers

for l in range(0, layers.__len__() - 1):
   weights[layers[l]] = np.random.rand(
      layers[l + 1].node_cardinality, 
      layers[l].node_cardinality + 1 
   )

Есть ли лучший, более короткий способ сделать это без использования кода range()?

Ответы [ 2 ]

0 голосов
/ 04 марта 2019

Я бы предложил пойти с перечислить и понимание слова .Это более питонно и, вероятно, быстрее.

layers = self.layers
buf_dict = {layers[i]: np.random.rand(layers[i + 1].node_cardinality, layers[i].node_cardinality + 1)
for i, l in zip(layers, layers[1:])}
weights.update(buf_dict)

Редактировать: Забыл код и признал, что zip на самом деле лучше, чем перечислять в этом случае (благодаря gilch), потому что вы не столкнетесь с IndexError.

0 голосов
/ 04 марта 2019

Zip со слоями и частью слоев, которая начинается со второго элемента.Обратите внимание, что zip() остановится, как только истечет любая из его итераций.

for L0, L1 in zip(layers, layers[1:]):
   weights[L0] = np.random.rand(
       L1.node_cardinality, 
       L0.node_cardinality + 1 
   )

В зависимости от типа последовательности layers, может быть более эффективно использовать itertools.islice вместонормальный срез.Numpy массив, вероятно, будет просто использовать представление, если вы нарежете.Но список должен был бы создать (неглубокую) копию, поэтому островок лучше, если он очень длинный.

for L0, L1 in zip(layers, islice(layers, 1, None)):
   weights[L0] = np.random.rand(
       L1.node_cardinality, 
       L0.node_cardinality + 1 
   )

Как указывал GrazingScientist, это также можно сделать с помощью точного понимания.

weights.update(
    {
        L0: np.random.rand(L1.node_cardinality, L0.node_cardinality + 1)
        for L0, L1 in zip(layers, layers[1:])
    }
)

Но этот подход должен будет генерировать новый dict перед обновлением, что может занять больше памяти.Цикл for, вероятно, лучше, если layers длинный.Но дикты содержат только ссылки, так что это, вероятно, не намного хуже, чем использование обычного среза списка.

В этом случае было бы более эффективно использовать выражение генератора.Метод .update() также может принимать итерируемые пары (k, v), но генератору не нужно выделять их все сразу.Это просто делает пару за один раз.

weights.update(
    (L0, np.random.rand(L1.node_cardinality, L0.node_cardinality + 1))
    for L0, L1 in zip(layers, islice(layers, 1, None))
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...