def safe_filter(x):
if x is None:
return ''
else
return x
row = map(safe_filter, row)Можно ли это записать в одну строку? (python 2.4)
Всё оказалось просто: map(lambda x: (x is not None and x) or "", row). Хотя, согласен, менее красиво.
Решил проверить на скорость и обнаружил...
Python 2.5.2 (r252:60911, Mar 13 2008, 07:28:35)
on linux2
>>> List = range(1000) + [None]*100
>>> import random
>>> random.shuffle(List)
>>> import timeit
>>> timeit.Timer('map(lambda x: (x is not None and x) or "", List)', 'from __main__ import List').timeit(10000)
11.695267200469971
>>> timeit.Timer('[{None: ""}.get(x, x) for x in List]', 'from __main__ import List').timeit(10000)
21.314514017105103
>>>Python 2.4.3 (#1, Nov 24 2006, 14:55:15)on linux2
>>> timeit.Timer('map(lambda x: (x is not None and x) or "", List)', 'from __main__ import List').timeit(10000)
14.910423994064331
>>> timeit.Timer('[{None: ""}.get(x, x) for x in List]', 'from __main__ import List').timeit(10000)
24.059360027313232Результаты перепроверил неоднократно.У меня PIII - 1000MHz, шина памяти 133MHz. Средняя заточка всея софта ('-O2').
-- Я -- часть той силы, что вечно хочет зла
и вечно совершает благо.
Но тут бесспорно lambda лучше, ибо это функция, а не объект с вызовом его же метода... { } => объект и все его методы....
Мысли в слух Ж)
P.S. функция поди тоже объект... только с меньшим количеством методов
dir({})
Last edited April 4, 2008, 8:28 p.m.
ZZZТвой вариант работает не корректно.
Мне стало интересно как поставленную задачу реализовать в моей стилистике.
Всё оказалось просто: map(lambda x: (x is not None and x) or "", row).
Он вместо нуля тоже ставит '', и вместо False.
Если же ты эту часть сделаешь через get тоже - то она будет работать медленнее чем на списковых включениях. (IMHO)
Last edited April 4, 2008, 9:57 p.m.
SHIZAТы прав, но для строк пойдёт.
Твой вариант работает не корректно.
Он вместо нуля тоже ставит '', и вместо False.
Если же ты эту часть сделаешь через get тоже - то она будет работать медленнее чем на списковых включениях. (IMHO)
Но почему именно get? Стоит немножко напрячь мозги и... TADAAA!!!
>>> map(lambda x: x or ((x is not None or '') and x), [0.0, 0, 1, 2, 3, None, 4, False, (), []])
[0.0, 0, 1, 2, 3, '', 4, False, (), []]Так лучше?Не поленился даже протестить. Так, для приличия...
Python 2.5.2 (r252:60911, Mar 13 2008, 07:28:35)
on linux2
>>> List = range(1000) + [None]*100
>>> import random
>>> random.shuffle(List)
>>> import timeit
>>> timeit.Timer('map(lambda x: x or ((x is not None or "") and x), List)', 'from __main__ import List').timeit(10000)
9.3463799953460693
>>> timeit.Timer('map(lambda x: x or ((x is not None or "") and x), List)', 'from __main__ import List').timeit(10000)
9.2854440212249756
>>> timeit.Timer('map(lambda x: x or ((x is not None or "") and x), List)', 'from __main__ import List').timeit(10000)
9.2770500183105469Мне кажется, что это того стоит.P.S. Тем кто читал этот пост до правки (между часом и двумя тридцати ночи) большое сорри. Затупил. Спать больше надо... а пить меньше...
Last edited April 5, 2008, 5:29 a.m.
-- Я -- часть той силы, что вечно хочет зла
и вечно совершает благо.
lorienВ большенстве случаев я тоже, но вот столкнувшись с подобной промлемой на сервере, я выберу скорость. Да и от размера списка зависит -- десять секунд или двадцать... В два раза как-никак...
я предпочту тормозной, но более читаемый вариант )
P.S. Ещё раз сорри за глючный пост...
-- Я -- часть той силы, что вечно хочет зла
и вечно совершает благо.
Меряем скорость:
import random
import timeit
row = range(1000) + [None]*100
random.shuffle(row)
#[{None: ''}.get(x, x) for x in row]
print timeit.Timer("[{None: ''}.get(x, x) for x in row]", 'from __main__ import row').timeit(10000)
#map(lambda x: x or ((x is not None or '') and x), row)
print timeit.Timer("map(lambda x: x or ((x is not None or '') and x), row)", 'from __main__ import row').timeit(10000)
#[x or ((x is not None or '') and x) for x in row]
print timeit.Timer("[x or ((x is not None or '') and x) for x in row]", 'from __main__ import row').timeit(10000)6.940563674994.07628818747
1.47561380008
Разница почти в 3 раза =)
Last edited April 5, 2008, 2:59 p.m.
SHIZA
Разница почти в 3 раза =)
>>> timeit.Timer('[x or ((x is not None or "") and x) for x in List]', 'from __main__ import List').timeit(10000)
4.5568611621856689Ты жжёшь! Ну прямо Мичурин какой-то... :-)Пока был в оффлайне, надумал такую штуку. Я поставил тебе вопрос: почему первый вариант такой тормозной? А ведь всё как всегда элементарно! Для кажной обработки у нас создаётся новый словарь. При том, чем больше этот словарь, тем больше тормоз:
>>> timeit.Timer('[{None: ""}.get(x, x) for x in List]', 'from __main__ import List').timeit(10000)
21.343222856521606
>>> timeit.Timer('[{None: "", 1:2}.get(x, x) for x in List]', 'from __main__ import List').timeit(10000)
26.878964185714722
>>> timeit.Timer('[{None: "", 1:2, 2:3}.get(x, x) for x in List]', 'from __main__ import List').timeit(10000)
31.339015960693359Если же создать этот словарь заранее, то по скорости оно почти сравняется с моим вариантом.>>> __ = {None: ''}; timeit.Timer('[__.get(x, x) for x in List]', 'from __main__ import List, __').timeit(10000)
12.067402124404907
>>> __ = {None: ''}; timeit.Timer('[__.get(x, x) for x in List]', 'from __main__ import List, __').timeit(10000)
12.022394895553589
>>> __ = {None: '', 1:2, 2:3}; timeit.Timer('[__.get(x, x) for x in List]', 'from __main__ import List, __').timeit(10000)
12.213709115982056
>>> __ = {None: '', 1:2, 2:3}; timeit.Timer('[__.get(x, x) for x in List]', 'from __main__ import List, __').timeit(10000)
12.240325212478638До SHIZA, конечно, далеко, но зато гораздо более функционально.Я думаю, что это, довольно действенный метод, для создания списка из любого iterable, с заменой значений.
P.S. Думаю, что тема исчерпана...
-- Я -- часть той силы, что вечно хочет зла
и вечно совершает благо.