有没有更简单的方法在字典值上运行函数而不失去键的关联?

1 投票
2 回答
865 浏览
提问于 2025-04-18 12:19

我想对字典里的所有值运行一个函数。不过事情有点复杂,因为每个值的变化并不是独立的,而是要依赖于之前其他值的变化。

这里有一个简单的函数,定义在一个列表上,来说明我的意思:

def new_list_generator(mylist):
    number_of_iterations = 0
    new_list  = []
    for n in mylist:
        if number_of_iterations%2 == 0:
            new_list.append(n**1.25)
            number_of_iterations += 1
        else:
            new_list.append(n**0.5)
            number_of_iterations += 1
    return new_list

你可以看到,我们对每个值的处理是依赖于历史的,也就是在它之前有多少个值被修改过。

现在,这个函数是针对列表定义的。如果我想修改字典里的值,但又不想把键和值分开(也就是说,我不想简单地把所有值放到一个列表里,然后把这个列表传给函数),那该怎么办呢?

我想到的最好的解决办法(并且能让它工作)是这样一个繁琐的步骤:

第一步:把字典转换成一个元组的列表。也就是像这样:[(value1,key1), (value2,key2),...]

第二步:在这个列表上运行一个修改过的函数。

第三步:用 dict() 把列表再转换回字典。

也就是说:

some_dict = {"Graham": 13, "Eric": 19, "Terry G": 7, "Terry J":11, "John": 15, "Michael": 7}

dict_to_tuples = some_dict.items()

def new_list_generator1(mylist):      # notice it's a new function
    number_of_iterations = 0
    new_list  = []
    for n in mylist:
        if number_of_iterations%2 == 0:
            new_list.append((n[0],n[1]**1.25))   # <== new
            number_of_iterations += 1
        else:
            new_list.append((n[0],n[1]**0.5))    # <== new
            number_of_iterations += 1
    return new_list

tups = new_list_generator1(dict_to_tuples)

print dict(tups)

我在想有没有更简单的方法来做到这一点,希望不需要修改原来的列表。我在网上查了查,发现 Stackoverflow 或其他地方都没有关于这个问题的有用信息(也就是当字典值的处理依赖于历史时)。

谢谢你的帮助。

2 个回答

0

正如评论中提到的,按照字典的遍历顺序来处理值是有点奇怪的,因为这个顺序并不是固定的,所以每次你应用这个函数时,可能会得到不同的结果。不过,如果你在处理时只考虑遍历的步骤,那么你可以简单地使用字典推导式:

{key: some_dict[key]**([1.25, 0.5][i % 2]) for i, key in enumerate(some_dict)}

或者更一般地说

def process_value(value, iteration_step):
    # new_value = ...
    return new_value

{key: process_value(some_dict[key], i) for i, key in enumerate(some_dict)}
1

只需要遍历这些键,然后直接修改对应的值就可以了。

some_dict = {"Graham": 13, "Eric": 19, "Terry G": 7, "Terry J":11, "John": 15, "Michael": 7}


def new_list_generator1(mydict):      # notice it's a new function
    number_of_iterations = 0
    for key in mydict:
        if number_of_iterations%2 == 0:
            mydict[key] = mydict[key]**1.25
        else:
            mydict[key] = mydict[key]**0.5
        number_of_iterations += 1
    return mydict

print new_list_generator1(some_dict)

正如@kroolik在下面正确指出的,这个过程可以进一步简化,至少在当前这个例子中可以使用enumerate

def new_list_generator1(mydict):      # notice it's a new function
    for i, key in enumerate(mydict):
        if i%2 == 0: mydict[key] = mydict[key]**1.25
        else: mydict[key] = mydict[key]**0.5
    return mydict

撰写回答