Понимания списка в Python: эффективный выбор в списке

Путем я сделал это, прежде чем будет путем инстанцирования LocalSessionFactoryBean и установки configLocation свойства.

9
задан ThibThib 3 August 2009 в 14:30
поделиться

7 ответов

Конечно, разница между следующими двумя:

[f(x) for x in list]

и этим:

(f(x) for x in list)

заключается в том, что первый будет генерировать список в памяти, а второй - новый генератор с ленивым оценка.

Итак, вместо этого просто напишите "неотфильтрованный" список в качестве генератора. Вот ваш код со встроенным генератором:

def myFunction(x):
    print("called for: " + str(x))
    return x * x

originalList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
limit = 10
result =   [C2 for C2 in ((myFunction(C), C) for C in originalList) if C2[0] < limit]
# result = [C2 for C2 in [(myFunction(C), C) for C in originalList] if C2[0] < limit]

Обратите внимание, что вы не увидите разницы в распечатке из двух, но если бы вы были чтобы посмотреть на использование памяти, второй закомментированный оператор будет использовать больше памяти.

Чтобы внести простое изменение в код в вашем вопросе, перепишите без фильтров, как это:

unfiltered = [ (myFunction(C),C) for C in originalList ]
             ^                                         ^
             +---------- change these to (..) ---------+
                                 |
                                 v
unfiltered = ( (myFunction(C),C) for C in originalList )
9
ответ дан 4 December 2019 в 12:20
поделиться

_cancelled должна быть изменчивой . (если вы не выбрали блокировку)

Если один поток изменяет значение _cancelled , другие потоки могут не видеть обновленный результат.

Кроме того, я думаю, что операции чтения / записи _cancelled являются атомарными :

Раздел 12.6.6 спецификации CLI гласит: "Соответствующий интерфейс командной строки должен гарантировать, что доступ для чтения и записи к правильному выровненные ячейки памяти не больше чем исходный размер слова атомарен когда все записи обращаются к При рисовании пунктирных линий вы можете варьировать расстояние между штрихами, чтобы убедиться, что у вас никогда не будет частичных четырехугольников на конечных точках. Это может визуально отвлекать, так как расстояние будет регулироваться в зависимости от длины сегмента.

редактировать:

А, картинка помогает. Я предполагаю, что, поскольку это на iPhone, вы получаете серию точек, из которых линии между ними дают приемлемую кривую. Если это так, использование примитивов сплайнов / кривых, вероятно, излишне. Я бы, вероятно, подошел к рисованию линий, как показано, просто путем рисования четырехугольников в каждой точке данных, которая находится на заданном расстоянии от последней точки данных.

Алгоритм выглядит примерно так:

  1. Нарисовать квад на первой точке данных (с соответствующим поворотом)
  2. Перемещайтесь по списку точек, пока не ' идентичные URL-адреса в карте сайта (которые запрещено в готовом виде t использовать понимание списка; нормальный цикл for здесь подойдет.

3
ответ дан 4 December 2019 в 12:20
поделиться

Некоторые параметры:

  • Использовать мемоизацию
  • Использовать обычный цикл for
  • Создать нефильтрованный список, затем отфильтровать его (ваш вариант 1). «Потраченная впустую» память будет восстановлена ​​сборщиком мусора очень быстро - это не то, о чем вам нужно беспокоиться.
1
ответ дан 4 December 2019 в 12:20
поделиться

Просто заранее вычислите расстояния, а затем отфильтруйте результаты:

with_distances = ((myFunction(C), C) for C in originalList)
result = [C for C in with_distances if C[0] < limit]

Примечание: вместо построения нового списка я использую выражение генератора для построения пар расстояние / элемент.

Подумайте о 160 КБ памяти или около того. Вряд ли стоит говорить.

0
ответ дан 4 December 2019 в 12:20
поделиться

Lasse V. Karlsen has an excellent reply to your question.

If your distance computation is slow, I guess your elements are polylines, or something like that, right ?

There are lots of ways to make it faster :

  • If the distance between bounding boxes of objects is > X, then it follows that the distance between those objects is > X. So you only need to compute distance between bounding boxes.

  • If you want all objects that are at a distance less than X from object A, only objects whose bounding box intersect A's bounding box enlarged by X are potential matches.

Using the second point you can probably drop lots of candidate matches and only do the slow computation when needed.

Bounding boxes must be cached beforehand.

If you really have a lot of objects you could also use space partitioning...

Or convex enclosing polys if you are in 3D

1
ответ дан 4 December 2019 в 12:20
поделиться

Просто заранее вычислите расстояния, а затем отфильтруйте результаты:

with_distances = ((myFunction(C), C) for C in originalList)
result = [C for C in with_distances if C[0] < limit]

Примечание: вместо построения нового списка я использую выражение генератора для построения пар расстояние / элемент.

3
ответ дан 4 December 2019 в 12:20
поделиться

Вместо того, чтобы использовать глобальную переменную, как в вашем варианте 2, вы могли бы полагаться на тот факт, что в Python параметры передаются по объекту, то есть объекту, который передается в ваш Функция myFunction - это тот же объект , что и в списке (это не совсем то же самое, что вызов по ссылке, но достаточно близко).

Итак, если ваш myFunction установлен атрибут объекта - скажем, _result - вы можете отфильтровать по этому атрибуту:

result = [(_result, C) for C in originalList if myFunction(C) < limit]

, и ваша myFunction может выглядеть следующим образом:

def myFunction(obj):
    obj._result = ... calculation ....
    return obj._result
0
ответ дан 4 December 2019 в 12:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: