我想写一个Rem(a, b),它返回一个新的元组,就像a一样,第一次出现的元素b被删除了。例如
返回(0, 9, 1, 4)的Rem((0, 1, 9, 1, 4), 1)。
我只被允许使用高阶函数,比如lambda、filter、map和reduce。
我正在考虑使用过滤器,但这将删除所有的匹配元素
def myRem(T, E):
return tuple(filter(lambda x: (x!=E), T))myRem((0, 1, 9, 1, 4), 1)我会有(0,9,4)
发布于 2018-02-13 17:23:23
以下代码有效(警告: hacky代码):
tuple(map(lambda y: y[1], filter(lambda x: (x[0]!=T.index(E)), enumerate(T))))但是,除非要求严格,否则我永远不会推荐这样做。
发布于 2018-02-13 17:40:31
临时列表的诀窍:
def removeFirst(t, v):
tmp_lst = [v]
return tuple(filter(lambda x: (x != v or (not tmp_lst or v != tmp_lst.pop(0))), t))
print(removeFirst((0, 1, 9, 1, 4), 1))tmp_lst.pop(0) -将仅调用一次(因此,排除第一次出现关键值v)not tmp_lst -由于此条件,将包括所有剩余/可能出现的情况
输出:
(0, 9, 1, 4)发布于 2018-02-13 17:44:33
有趣的是,使用itertools,你可以使用更高阶的函数...
>>> from itertools import *
>>> data = (0, 1, 9, 1, 4)
>>> not1 = (1).__ne__
>>> tuple(chain(takewhile(not1, data), islice(dropwhile(not1, data), 1, None)))
(0, 9, 1, 4)顺便说一句,这里是一些比较删除元组中特定索引的不同方法的计时:
>>> timeit.timeit("t[:i] + t[i+1:]", "t = tuple(range(100000)); i=50000", number=10000)
10.42419078599778
>>> timeit.timeit("(*t[:i], *t[i+1:])", "t = tuple(range(100000)); i=50000", number=10000)
20.06185237201862
>>> timeit.timeit("(*islice(t,None, i), *islice(t, i+1, None))", "t = tuple(range(100000)); i=50000; from itertools import islice", number=10000)
>>> timeit.timeit("tuple(chain(islice(t,None, i), islice(t, i+1, None)))", "t = tuple(range(100000)); i=50000; from itertools import islice, chain", number=10000)
19.71128663700074
>>> timeit.timeit("it = iter(t); tuple(chain(islice(it,None, i), islice(it, 1, None)))", "t = tuple(range(100000)); i=50000; from itertools import islice, chain", number=10000)
17.6895881179953看起来很难击败简单的:t[:i] + t[i+1:],这并不令人惊讶。
请注意,这个版本的性能差得令人震惊:
>>> timeit.timeit("tuple(j for i, j in enumerate(t) if i != idx)", "t = tuple(range(100000)); idx=50000", number=10000)
111.66658291200292这使得我认为,所有这些使用takewhile、filter和lambda的解决方案都将遭受相当糟糕的影响……
尽管:
>>> timeit.timeit("not1 = (i).__ne__; tuple(chain(takewhile(not1, t), islice(dropwhile(not1, t), 1, None)))", "t = tuple(range(100000)); i=50000; from itertools import chain, takewhile,dropwhile, islice", number=10000)
62.22159145199112生成表达式的速度几乎是生成器表达式的两倍,生成器开销可能相当大。然而,takewhile和dropwhile是用C语言实现的,尽管这个实现有冗余(take-while和dropwhile将两次通过dropwhile区域)。
另一个有趣的观察是,如果我们简单地用list-comp替换生成器表达式,那么它的速度要快得多,尽管列表理解+元组调用在结果上迭代了两次,而生成器表达式只迭代了一次:
>>> timeit.timeit("tuple([j for i, j in enumerate(t) if i != idx])", "t = tuple(range(100000)); idx=50000", number=10000)
82.59887028901721去展示生成器表达式的价格可以有多高。
https://stackoverflow.com/questions/48762887
复制相似问题