Что касается комментария, который я оставил вам.
У вас есть как минимум три состояния, когда вы извлекаете данные в пользовательский интерфейс. В этом случае я бы порекомендовал вам использовать агрегацию для извлечения данных в качестве модели вашего бизнеса.
Например, проблема, с которой вы столкнулись, заключается в том, что иногда вы не знаете о максимальном или минимальном значении для age или yearsActive , но также должны иметь идентификатор, который может быть ObjectId , который будет использоваться для обновления модели, идентифицируемой этим свойством.
Artist.aggregate([
{
$match: { age: { $gte: 19, $lte: 44 } }
},
{
$sort: { yourProperty: 1 }
},
{
$skip: 10
},
{
$limit: 10
},
{
$project: {
// You set your properties to retrieve with the 1 as flag
propertieX: 1,
"another.property": 1,
"age.max": {
$cond: {
if: { $eq: [ "", "$age.max" ] },
then: 0, // Or the value that you want to set it
else: "$age.max"
}
}
}
}]);
Другое состояние - когда вы делаете запрос в соответствии с параметрами, которые вы отправляете из формы.
Если вы уверены, что получите модель с логикой, как вы хотите. Например, вы должны возвращать эту модель в каждом запросе, используя $ project и применяя значения по умолчанию, когда их не существует, манипулирование на стороне интерфейса, как при поиске, должно быть простым в управлении.
{
ObjectId: YOUR_OBJECT_ID,
age: {
min: YOUR_MIN_VALUE,
max: YOUR_MAX_VALUE
},
yearsActive: {
min: YOUR_MIN_VALUE,
max: YOUR_MAX_VALUE
}
}
Наконец, когда вы отправляете данные, чтобы сохранить их, вы должны отправить всю возвращенную модель, но самое важное - идентифицировать только этот элемент с помощью ObjectId , чтобы выполнить обновление.
ПРИМЕЧАНИЕ. : . Этот подход я буду использовать в соответствии с информацией, которую я понимаю из вашего вопроса. Если мне плохо со мной в интерпретации, дайте мне знать, и если вы хотите поделиться дополнительной информацией или открыть репозиторий для понимания в коде, если мне будет легче понять проблему .
Если вычисления уже приятно связываются в функции, как насчет того, чтобы использовать filter
и map
?
result = filter (None, map (expensive, mylist))
можно использовать itertools.imap
, если список является очень большим.
Самое очевидное (и я спорил бы самый читаемый), ответ не должен использовать понимание списка или выражение генератора, а скорее реальный генератор:
def gen_expensive(mylist):
for item in mylist:
result = expensive(item)
if result:
yield result
Это занимает больше горизонтального места, но намного легче видеть то, что это делает сразу, и Вы заканчиваете тем, что не повторили себя.
result = [x for x in map(expensive,mylist) if x]
карта () возвратится, список значений каждого объекта в mylist передал дорогому (). Тогда можно перечислить - постигают это и отбрасывают ненужные значения.
Это несколько похоже на вложенное понимание, но должно быть быстрее (так как интерпретатор Python может оптимизировать его довольно легко).
Это точно, что генераторы подходят обрабатывать:
result = (expensive(x) for x in mylist)
result = (do_something(x) for x in result if some_condition(x))
...
result = [x for x in result if x] # finally, a list
cf: 'Приемы генератора для Системных программистов' David Beazley
Придумал мой собственный ответ после минуты мысли. Это может быть сделано с вложенными пониманиями:
result = [y for y in (expensive(x) for x in mylist) if y]
я предполагаю, что работы, хотя я нахожу вложенные понимания, только незначительно читаемы
Вы всегда могли memoize эти expensive()
функция так, чтобы вызов его во второй раз вокруг был просто поиском для вычисленного значения x
.
Вот только одна из многих реализаций memoize как декоратор .
Вы могли memoize дорогой (x) (и если Вы называете дорогими (x) часто, Вы, вероятно, должны memoize это любой путь. Эта страница дает реализацию memoize для Python:
http://code.activestate.com/recipes/52201/
Это обладает дополнительным преимуществом, которое дорогой (x) может быть выполнено меньше , чем времена N, так как любые дублирующиеся записи используют записку от предыдущего выполнения.
Примечание, которое это принимает дорогой (x), является истинной функцией и не зависит от внешнего состояния, которое может измениться. Если дорогой (x) действительно зависит от внешнего состояния, и можно обнаружить, когда это изменения состояния, или Вы знаете это привычка изменение во время Вашего понимания списка, то можно сбросить записки перед пониманием.
I will have a preference for:
itertools.ifilter(bool, (expensive(x) for x in mylist))
This has the advantage to:
Существует простое старое использование цикла for
для добавления в список:
result = []
for x in mylist:
expense = expensive(x)
if expense:
result.append(expense)