没有填充值的zip_longest [英] zip_longest without fillvalue
问题描述
我正在寻找Python的 zip
和 zip_longest
函数之间的中间地带(来自 itertools 模块),它耗尽了所有给定的迭代器,但不填充任何内容。因此,例如,它应该像这样转换元组:
$ b
(11,12,13) ,(11,21,31,41),
(21,22,23,24), - > (12,22,32,42),
(31,32),(13,23,43),
(41,42,43,44),(24,44)
(为更好的图形对齐而添加的空格)
我通过清理 fillvalue
s之后的 zip_longest
。
$ b
def zip_discard(* iterables,sentinel = object()) :
return map(
partial(filter,partial(is_not,sentinel)),
zip_longest(* iterables,fillvalue = sentinel))
有没有办法在不引入标记的情况下执行此操作?这可以通过使用 yield
来改善吗?哪种方法看起来效率最高?
您的方法很好。我认为使用哨兵很优雅。我可能会认为使用嵌套的生成器表达式会更加pythonic:
def zip_discard_gen(* iterables,sentinel = object() ):
return((如果条目不是哨兵,则在迭代中输入条目)
在zip_longest(* iterables,fillvalue = sentinel)中迭代)
因为不需要 partial()
或 ne ()
。
它也更快一些:
data = [(11,12,13),
(21,22,23,24),
(31,32),
(41,42,
%timeit [zip_discard(* data)中x的列表(x)]
10000循环,最好是3:每循环17.5μs
%timeit [zip_discard_gen(* data)中x的列表(x)]
100000循环,最好是3:每循环14.2μs
编辑
列表理解版本更快一些:
def zip_
return [[如果条目不是sentinel,则为iterable中的条目]
为zip_longest中的iterable(* iterables,fillvalue = sentinel)]
计时:
%timeit zip_discard_compr(* data)
100000循环,最好是3:每循环6.73微秒
一个Python 2版本:
from itertools import izip_longest
SENTINEL = object()
def zip_discard_compr(* iterables):
sentinel = SENTINEL
return [[迭代条目入口不是sentinel的入口]
迭代的izip_longest ,fillvalue = sentinel)]
定时
该版本返回与code $ zip_varlen 相同的数据结构
Tadhg McDonald-Jensen:
def zip_discard_gen(* iterables,sentinel = object()):
return(tuple([entry for ent ry in iterable如果入口不是sentinel])
for iterable in zip_longest(* iterables,fillvalue = sentinel))
它的速度快了一倍:
%timeit list(zip_discard_gen(* data))
100000个循环,最好是3:每循环9.37μs
%timeit list(zip_varlen(* data))
10000循环,最好是3:每循环18μs
I am searching for a middle ground between Python's zip
and zip_longest
functions (from the itertools module), that exhausts all given iterators, but does not fill in anything. So, for example, it should transpose tuples like so:
(11, 12, 13 ), (11, 21, 31, 41),
(21, 22, 23, 24), --> (12, 22, 32, 42),
(31, 32 ), (13, 23, 43),
(41, 42, 43, 44), ( 24, 44)
(Spaces added for nicer graphical alignment.)
I managed to compose a crude a solution by cleaning out the fillvalue
s after zip_longest
.
def zip_discard(*iterables, sentinel = object()):
return map(
partial(filter, partial(is_not, sentinel)),
zip_longest(*iterables, fillvalue=sentinel))
Is there a way to do this without introducing the sentinels to begin with? Can this be improved using yield
? Which approach seems most efficient?
You approach is good. I think using a sentinel is elegant. I might be considered a bit more pythonic to use a nested generator expression:
def zip_discard_gen(*iterables, sentinel=object()):
return ((entry for entry in iterable if entry is not sentinel)
for iterable in zip_longest(*iterables, fillvalue=sentinel))
This needs fewer imports because there is no need for partial()
or ne()
.
It is a bit faster too:
data = [(11, 12, 13 ),
(21, 22, 23, 24),
(31, 32 ),
(41, 42, 43, 44)]
%timeit [list(x) for x in zip_discard(*data)]
10000 loops, best of 3: 17.5 µs per loop
%timeit [list(x) for x in zip_discard_gen(*data)]
100000 loops, best of 3: 14.2 µs per loop
EDIT
A list comprehension version is a bit faster:
def zip_discard_compr(*iterables, sentinel=object()):
return [[entry for entry in iterable if entry is not sentinel]
for iterable in zip_longest(*iterables, fillvalue=sentinel)]
Timing:
%timeit zip_discard_compr(*data)
100000 loops, best of 3: 6.73 µs per loop
A Python 2 version:
from itertools import izip_longest
SENTINEL = object()
def zip_discard_compr(*iterables):
sentinel = SENTINEL
return [[entry for entry in iterable if entry is not sentinel]
for iterable in izip_longest(*iterables, fillvalue=sentinel)]
Timings
This version returns the same data structure as zip_varlen
by
Tadhg McDonald-Jensen:
def zip_discard_gen(*iterables, sentinel=object()):
return (tuple([entry for entry in iterable if entry is not sentinel])
for iterable in zip_longest(*iterables, fillvalue=sentinel))
It is about twice as fast:
%timeit list(zip_discard_gen(*data))
100000 loops, best of 3: 9.37 µs per loop
%timeit list(zip_varlen(*data))
10000 loops, best of 3: 18 µs per loop
这篇关于没有填充值的zip_longest的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!