2010-10-07 3 views
1
for i in vr_world.getNodeNames(): 
    if i != "_error_": 
     World[i] = vr_world.getChild(i) 

vr_world.getNodeNames() возвращает мне гигантский список, vr_world.getChild (i) возвращает определенный тип объекта.Более эффективные способы сделать это

Это займет много времени, чтобы работать, есть ли способ сделать его более эффективным? Я видел однострочные циклы для петель, прежде чем они должны быть быстрее. Идеи?

+0

'.getNodeNames()' запускается только один раз, когда вы вводите цикл 'for', поэтому, если это займет некоторое время, исправьте это (если возможно). Независимо от того, как вы это делаете (например, с учетом списков - однострочники, на которые вы ссылаетесь), по-видимому, вам нужно будет получить данные, которые функция выйдет каким-то образом. –

+5

один лайнер! = Быстрый –

+1

Пропустили ли вы свой код через профилировщик, чтобы узнать, что * часть * этого медленно? – Daenyth

ответ

1

kaloyan предлагает использовать генератор. Вот почему это может помочь.

Если getNodeNames() строит список, то ваш цикл в основном проходит по списку дважды: один раз для его создания и один раз, когда вы перебираете список.

Если getNodeNames() является генератором, то ваша петля никогда не будет создавать список; вместо создания элемента и добавления его в список он создает элемент и возвращает его вызывающему.

Независимо от того, зависит ли это от нескольких вещей. Во-первых, это должно быть возможно реализовать getNodeNames() в качестве генератора. Мы ничего не знаем о деталях реализации этой функции, поэтому нельзя сказать, если это так. Затем количество элементов, которые вы повторяете, должно быть довольно большим.

Конечно, ничто из этого не будет иметь никакого эффекта, если окажется, что отнимающая много времени операция составляет всего vr_world.getChild(). Вот почему вам нужно профилировать свой код.

0
World = dict((i, vr_world.getChild(i)) for i in vr_world.getNodeNames() if i != "_error_") 

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

+0

Действительно ли это более эффективно или просто более компактно? – GWW

+0

Это действительно не делало ничего лучше - или хуже. Возможно, это в getChild, где проблема на самом деле. – relima

+0

@GWW выражение генератора будет _normally_ быть на 10-100% быстрее, чем эквивалентный цикл 'for', хотя я видел случаи, когда они медленнее. – aaronasterling

0

Может быть, вы можете использовать фильтр и карту, но я не знаю, если это будет какой-либо быстрее:

valid = filter(lambda i: i != "_error_", vr_world.getNodeNames()) 
World = map(lambda i: vr_world.getChild(i), valid) 

Кроме того, как вы будете видеть много здесь, профиль, а затем оптимизировать, в противном случае вы можете тратить время. У вас есть две функции, возможно, это медленные части, а не итерация.

+2

К сожалению, в python решения 'filter' /' map' почти всегда медленнее, чем списки. – Daenyth

+1

, если скорость является фактором в первой строке: 'valid = filter ('_ error _'.__ eq__, vr_world.getNodeNames())' – eumiro

+0

Кроме того, лямбда-функции медленнее, чем обычные, или, как в случае выше, встроенная логика. – ktdrv

1

Я не думаю, что вы можете сделать это быстрее, чем то, что у вас там есть. Да, вы можете положить все это на одну строку, но это не ускорится. Узким местом является, очевидно, getNodeNames(). Если вы можете сделать это генератором, вы начнете заполнять World dict с результатами раньше (если это имеет значение для вас), и если вы отфильтруете значения "_error_", вы не будете иметь дело с этим на более позднем этапе.

Смежные вопросы