Задача 1
У меня есть четыре списка одинаковой длины: A_old, A_new, B_old, B_new
, и я хочу иметь следующее поведение: Если A_new[i] > A_old[i]
, то установить B_old[i] = B_new[i]
.
Попробовал простой циклреализация:
for i, (a_new, a_old) in enumerate(izip(A_new, A_old)):
if a_new > a_old:
B_old[i] = B_new[i]
И реализация, использующая карту (как предлагается здесь ):
B_old = map(lambda (a_new, a_old, b_new, b_old): b_new if a_new > a_old else b_old,
izip(A_new, A_old, B_new, B_old))
Но ни один из этих подходов не является достаточно быстрым.Обратите внимание, что я не могу использовать массивы numpy
и логические массивы, потому что элементы B_new, B_old
не являются числовыми.
Чтобы поставить вещи на более формальную основу, здесь приведен пример реализации: https://gist.github.com/1986588 и время выполнения, как показано ниже:
Naive: 1.13343191147
Mapping: 1.45240283012
kev: 1.09499907494
Numpy: 0.0525879859924
Where: 0.0651860237122
Задача 2
Оценив различные варианты numpy
нарезка с логическими массивами, кажется, путь.Однако теперь я столкнулся с новой проблемой:
Пусть B_new
будет не массивом, а просто значением val
.Тогда лучший вариант читает:
B_old[A_new > A_old] = val
Это прекрасно работает, пока val
не повторяется, но завершается ошибкой.В частности, val
здесь кортеж.Я хотел бы присвоить кортеж val
элементам B_old
, где A_new > A_old
.
Обходным решением может быть разрешение
val2 = np.empty(1, dtype=object)
val2[0]=val
B_old[A_new > A_old] = val
, но это кажется запутанным.Проблема в том, что я не знаю, какой тип val.Это может быть повторяемым и не может быть.