将函数应用于Python中列表的一个元素

时间:2010-04-02 06:09:20

标签: python list-comprehension

我正在寻找一种简洁实用的样式方法,将函数应用于元组的一个元素并以Python格式返回新元组。

例如,对于以下输入:

inp = ("hello", "my", "friend")

我希望能够得到以下输出:

out = ("hello", "MY", "friend")

我想出了两个我不满意的解决方案。

一个人使用更高阶的功能。

def apply_at(arr, func, i):
    return arr[0:i] + [func(arr[i])] + arr[i+1:]

apply_at(inp, lambda x: x.upper(), 1)

一个使用列表推导(这个假定元组的长度已知)。

[(a,b.upper(),c) for a,b,c in [inp]][0]

有更好的方法吗?谢谢!

6 个答案:

答案 0 :(得分:6)

这是一个适用于任何iterable并返回生成器的版本:

>>> inp = ("hello", "my", "friend")
>>> def apply_nth(fn, n, iterable):
...    return (fn(x) if i==n else x for (i,x) in enumerate(iterable))
... 
>>> tuple(apply_nth(str.upper, 1, inp))
('hello', 'MY', 'friend')

您可以对此进行扩展,以便您可以为其提供一个位置列表,而不是一个位置:

>>> def apply_at(fn, pos_lst, iterable):
...    pos_lst = set(pos_lst)
...    return (fn(x) if i in pos_lst else x for (i,x) in enumerate(iterable))
... 
>>> ''.join(apply_at(str.upper, [2,4,6,8], "abcdefghijklmno"))
'abCdEfGhIjklmno'

答案 1 :(得分:2)

>>> inp = "hello", "my", "friend"
>>> index = 1
>>> inp[:index] + ( str.upper(inp[index]),) + inp[index + 1:]
('hello', 'MY', 'friend')

看起来很简单,你可能需要知道的唯一一件事就是制作单个元素元组,do(elt,)

答案 2 :(得分:2)

也许有些人喜欢这样?

>>>inp = ("hello", "my", "friend")
>>>out =  tuple([i == 1 and x.upper() or x for (x,i) in zip(t,range(len(t)))])

>>> out
('hello', 'MY', 'friend')

注意:而不是(x,i) in zip(t, range(len(t)))我应该考虑使用枚举函数:(i,x) in enumerate(t)

使它更通用:
我们可以将它放在一个变量中,而不是对1进行硬编码 此外,通过为此目的使用元组,我们可以将函数应用于多个索引处的元素。

>>>inp = ("hello", "my", "friend")
>>>ix  = (0,2)
>>>out =  tuple([i in ix and x.upper() or x for (i, x) in enumerate(t)])

>>> out
('HELLO', 'my', 'FRIEND')

此外,我们可以通过map()“替换”zip()/ enumerate(),例如

out = tuple(map(lambda x,i : i == 1 and x.upper() or x, inp, range(len(inp)) ) )

编辑:(解决有关指定要应用的功能的评论):
可能是一件简单的事情:

>>> f = str.upper  # or whatever function taking a single argument
>>> out = tuple(map(lambda x,i : i == 1 and f(x) or x, inp, range(len(inp)) ) )

由于我们正在谈论应用任何函数,我们应该提到condition and if_true or if_false构造的小警告,它不是完全替代if / else三元运算符在其他语言中找到。限制是函数不能返回一个等于False的值(例如,None,0,0.0,'')。建议避免这个问题,使用Python 2.5及更高版本,使用真正的if-else三元运算符,如Dave Kirby的答案所示(注意此运算符的when_true if condition else when_false语法)

答案 3 :(得分:1)

我评论说你支持你的第一个片段,但是还有其他一些记录方式:

(lambda (a,b,c): [a,b.upper(),c])(inp)

(不适用于Python 3.x.)并且:

[inp[0], inp[1].upper(), inp[1]]

答案 4 :(得分:0)

我不明白你是否想要将某个函数应用于通过某些测试的元组中的每个元素,或者你是否希望它将该函数应用于元组的某个索引处出现的任何元素。所以我编写了两种算法:

这是用于在函数式语言中解决此问题的算法(用Python编码):

此函数将识别id可识别的元素并将func应用于该元素,并返回一个列表,其中该元素已更改为func的输出。它将对可识别为id的每个元素执行此操作:

def doSomethingTo(tup, id):
    return tuple(doSomethingToHelper(list(tup), id))

def doSomethingToHelper(L, id):
    if len(L) == 0:
        return L
    elif L[0] == id:
        return [func(L[0])] + doSomethingToHelper(L[1:], id)
    else:
        return [L[0]] + doSomethingToHelper(L[1:], id)


此算法将在元组的索引处找到元素并将func应用于它,并将其粘贴回元组中的原始索引

def doSomethingAt(tup, i): 
    return tuple(doSomethingAtHelper(list(tup), i, 0))

def doSomethingAtHelper(L, index, i):
if len(L) == 0: 
        return L
elif i == index: 
        return [func(L[0])] + L[1:]
else: 
        return [L[0]] + doSomethingAtHelper(L[1:], index, i+1)

答案 5 :(得分:0)

我也喜欢Dave Kirby给出的答案。但是,作为公共服务公告,我想说这不是元组的典型用例 - 这些是源自Python的数据结构,作为将数据(参数,参数)移入和移出函数的手段。 ..它们并不是程序员在应用程序中用作通用数组结构的数据结构 - 这就是列表存在的原因。当然,如果你需要元组的只读/不可变特性,这是一个公平的论证,但考虑到OP问题,这应该是用列表来完成的 - 注意如何有额外的代码来拉动将元组分开并将结果放在一起和/或需要暂时转换为列表并返回。