首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >python元组仅使用高阶函数移除第一个匹配外观

python元组仅使用高阶函数移除第一个匹配外观
EN

Stack Overflow用户
提问于 2018-02-13 16:59:29
回答 5查看 256关注 0票数 3

我想写一个Rem(a, b),它返回一个新的元组,就像a一样,第一次出现的元素b被删除了。例如

返回(0, 9, 1, 4)Rem((0, 1, 9, 1, 4), 1)

我只被允许使用高阶函数,比如lambda、filter、map和reduce。

我正在考虑使用过滤器,但这将删除所有的匹配元素

代码语言:javascript
复制
def myRem(T, E):
    return tuple(filter(lambda  x: (x!=E), T))

myRem((0, 1, 9, 1, 4), 1)我会有(0,9,4)

EN

回答 5

Stack Overflow用户

发布于 2018-02-13 17:23:23

以下代码有效(警告: hacky代码):

代码语言:javascript
复制
tuple(map(lambda y: y[1], filter(lambda  x: (x[0]!=T.index(E)), enumerate(T))))

但是,除非要求严格,否则我永远不会推荐这样做。

票数 6
EN

Stack Overflow用户

发布于 2018-02-13 17:40:31

临时列表的诀窍:

代码语言:javascript
复制
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 -由于此条件

,将包括所有剩余/可能出现的情况

输出:

代码语言:javascript
复制
(0, 9, 1, 4)
票数 3
EN

Stack Overflow用户

发布于 2018-02-13 17:44:33

有趣的是,使用itertools,你可以使用更高阶的函数...

代码语言:javascript
复制
>>> 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)

顺便说一句,这里是一些比较删除元组中特定索引的不同方法的计时:

代码语言:javascript
复制
>>> 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:],这并不令人惊讶。

请注意,这个版本的性能差得令人震惊:

代码语言:javascript
复制
>>> timeit.timeit("tuple(j for i, j in enumerate(t) if i != idx)", "t = tuple(range(100000)); idx=50000", number=10000)
111.66658291200292

这使得我认为,所有这些使用takewhilefilterlambda的解决方案都将遭受相当糟糕的影响……

尽管:

代码语言:javascript
复制
>>> 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

生成表达式的速度几乎是生成器表达式的两倍,生成器开销可能相当大。然而,takewhiledropwhile是用C语言实现的,尽管这个实现有冗余(take-while和dropwhile将两次通过dropwhile区域)。

另一个有趣的观察是,如果我们简单地用list-comp替换生成器表达式,那么它的速度要快得多,尽管列表理解+元组调用在结果上迭代了两次,而生成器表达式只迭代了一次:

代码语言:javascript
复制
>>> timeit.timeit("tuple([j for i, j in enumerate(t) if i != idx])", "t = tuple(range(100000)); idx=50000", number=10000)
82.59887028901721

去展示生成器表达式的价格可以有多高。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48762887

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档