Объединение списков на основе поэлементного условия - PullRequest
1 голос
/ 06 марта 2012

Задача 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.Это может быть повторяемым и не может быть.

1 Ответ

3 голосов
/ 06 марта 2012
B_old = [B_new[i] if A_new[i]>A_old[i] else B_old[i] for i in range(len(A_old))]
...