简体   繁体   English

在python字典中随机替换2个值

[英]Randomly replace 2 values in python dictionary

Good day, 美好的一天,

First of all, I've seen many posts on this site that deal with similar problems, yet none of them offered a working solution. 首先,我在该站点上看到过许多处理类似问题的帖子,但没有一个提供有效的解决方案。 I'd highly appreciate if you'd take the time to at look my question before referring to another post. 如果您能在参考其他帖子之前花点时间看一下我的问题,将不胜感激。

I've been spending a few hours trying to figure out a simple way to replace two items in dictionary in a way that would take the items from two randomly selected pair of keys and switch between the two. 我已经花了几个小时试图找出一种简单的方法来替换字典中的两个项目,该方法可以从两个随机选择的键对中取出项目,然后在两者之间进行切换。 such as: 如:

dictionary1 = {'a':'A', 'b':'B', 'c':'C'}
dictionary2 = {'a':'B', 'b':'A', 'c':'C'}

Now, I understand that dictionaries don't have indexes, which makes the process a bit tricky. 现在,我了解到字典没有索引,这会使过程有些棘手。 So I've built this function: 所以我建立了这个功能:

def get_neighbor (dictionary1 ):
    dictionary1 = dictionary1 
    def keys_with_value(self, value):
        return [k for k, v in list(self.items()) if v == value]
    copy = {}
    copy = dictionary1 
    letter1 = random.choice(list(copy))
    letter2 = random.choice(list(copy))

    key1 =  (keys_with_value(copy,letter1))[0]
    key2 =  (keys_with_value(copy,letter2))[0]
    copy[key1] = letter2
    copy[key2] = letter1
    return copy

As you can see, the function takes dictionary1 and creates a copy. 如您所见,该函数接受Dictionary1并创建一个副本。 Then the function reassigns the keys and values of 2 randomly chosen letters. 然后,该函数将重新分配2个随机选择的字母的键和值。

Yet, when I'm trying to look into the function it appears that the end result effects BOTH the original (dictionary1) and the copy (dictionary2). 但是,当我尝试研究该函数时, 最终结果似乎同时影响原始(dictionary1)和副本(dictionary2)。

It seems as if both dictionaries are stored in the same place. 好像两个字典都存储在同一位置。 But that's impossible, right? 但这是不可能的,对吧?

I would highly appreciate any help/suggestion you guys (and girls) might provide! 非常感谢你们(和女孩)可能提供的任何帮助/建议!

It seems as if both dictionaries are stored in the same place. 好像两个字典都存储在同一位置。 But that's impossible, right? 但这是不可能的,对吧?

Actually, that's exactly what's happening. 实际上,这就是正在发生的事情。 Your line: 您的电话:

copy = dictionary1

makes copy another name for the object already named dictionary1 . 为已经命名为dictionary1的对象copy另一个名称。 It does not create a new dictionary containing the contents of dictionary1 . 它不会创建包含dictionary1内容的新dictionary1

Python variables are names for objects. Python变量是对象的名称。 Setting one variable equal to another assigns the name to the object, it does not copy the object. 将一个变量设置为与另一个变量相等将为该对象分配名称,但不会复制该对象。 There are various ways to do that - for one way to do a shallow copy, you can use: 有多种方法可以执行此操作-一种进行浅表复制的方法可以使用:

copy.update(dictionary1)

Or, as Red Alert noted in the comments above, copy = dictionary1.copy() . 或者,如上面评论中的Red Alert所述, copy = dictionary1.copy() That's better than declaring a new empty dict and using update . 这比声明一个新的空字典并使用update更好。

Or, for more safety, use the copy.deepcopy function. 或者,为了更加安全,请使用copy.deepcopy功能。 With the example you've shown here there would be no difference, but if your dictionary had lists or other mutable objects as values the shallow copy would copy references to the objects rather than new objects. 对于此处显示的示例,这没有什么区别,但是如果您的字典将列表或其他可变对象作为值,则浅表副本会将引用复制到对象,而不是新对象。

Some notes on mutable vs. immutable objects follow, based on the comments thread: 根据注释线程,以下是关于可变对象与不可变对象的一些说明:

It is common for implementations of Python (including the only one I can talk about with accuracy, the common C implementation) to reuse objects for some immutable objects. Python的实现(包括我可以准确地谈论的唯一一个,即通用的C实现)很常见,它会为一些不可变的对象重用对象。 For example, the following code in C Python will result in two references to the same object: 例如,C Python中的以下代码将导致对同一对象的两个引用:

x = 7
y = 7

Because 7 is immutable, it is safe to do this. 因为7是不可变的,所以这样做是安全的。 You can subsequently rebind x to a different object, eg: 随后,您可以将x重新绑定到其他对象,例如:

x = 9

This does not affect the shared object for 7 , and y will not change. 这不会影响7的共享对象,并且y不会更改。 This behavior is not special to immutable objects - x = 9 rebinds the name in the same way that x = [1, 2] would. 此行为对不可变对象并不特殊x = 9以与x = [1, 2]相同的方式重新绑定名称。 In neither case would y be affected. 在两种情况下会y受到影响。 What is special is the behavior of mutable objects - code like x = [1, 2]; x.append(3) 特殊之处在于易变对象的行为-类似于x = [1, 2]; x.append(3) x = [1, 2]; x.append(3) changes the underlying object. x = [1, 2]; x.append(3)更改基础对象。 Correct Python implementations will not reuse objects for mutable classes. 正确的Python实现将不会为可变类重用对象。

In general, you will not have to care about this implementation detail. 通常,您不必关心此实现细节。 Although it is true that x = 7; y = 7; x is y 尽管x = 7; y = 7; x is y是正确的x = 7; y = 7; x is y x = 7; y = 7; x is y x = 7; y = 7; x is y will return True in the C implementation of Python, code should not rely on this. x = 7; y = 7; x is y将在Python的C实现中返回True ,代码不应依赖于此。 Instead, it is best to write your code as if it were entirely possible that x and y would have different objects - you can't mutate those objects, so it should never matter. 相反,最好编写代码,就好像xy完全有可能具有不同的对象一样-您不能对那些对象进行突变,因此它永远都没有关系。 Instead, use the comparison functions like == - those work regardless of the implementation detail. 相反,请使用==之类的比较函数-无论实现细节如何,这些函数都可以工作。 And in fact numeric equality can easily be true in cases where object identity is not, such as x = 7; y = 7.0; x == y 实际上,在没有对象标识的情况下,例如x = 7; y = 7.0; x == y数值相等很容易成立x = 7; y = 7.0; x == y x = 7; y = 7.0; x == y x = 7; y = 7.0; x == y . x = 7; y = 7.0; x == y

All you actually have to worry about is whether you have other names for your mutable objects, such as: 您真正需要担心的是,可变对象是否具有其他名称,例如:

x = [1, 2]
y = x
y.append(3)

Python variables are always references to objects, but in some cases you can work with the objects as if they were values. Python变量始终是对对象的引用,但是在某些情况下,您可以将它们当作值来使用。 They aren't, but when you're doing things that are safe to do on shared objects (such as everything you can do to an integer) you don't have to care. 它们不是,但是当您在共享对象上执行安全的操作时(例如,您可以对整数执行的所有操作),您不必在意。

The one fly in this ointment is None . 这种药膏的一只苍蝇是None None is a singleton object - None is in fact a reference to a single immutable instance of NoneType . None是一个单独的对象- None其实是在一个单一的不变的实例的引用NoneType But because comparison logic can be written incorrectly, the correct way to check for None values is in fact to rely on that singleton nature and use x is None instead of x == None and run the risk that x 's equality check returns a false positive. 但是因为比较逻辑可能写错了,所以检查None值的正确方法实际上是依赖于该单例性质并使用x is None而不是x == None并冒着x的相等性检查返回false的风险。正。 I haven't checked the implementation details to see if it's even theoretically possible to create a second object of NoneType , but in any case nothing does. 我没有检查实现细节,以查看从理论上讲是否甚至可以创建NoneType的第二个对象,但是无论如何都无济于事。

You should make sure that when you are mutating an object, you either intend your mutations to affect all references to that object or that you make a copy first. 您应该确保在对一个对象进行突变时,要么使您的突变影响该对象的所有引用,要么首先创建一个副本。 Because it is impossible to mutate an immutable type like an int , you don't have to worry about this with int s, tuple s, frozenset s, or other built-in immutable types. 因为不可能对不可变类型(如int进行突变,所以您不必担心inttuple s, frozenset或其他内置的不可变类型。

You may want to use random.sample instead of random.choice . 您可能要使用random.sample而不是random.choice When you use random.sample you specify how many items you want and are guaranteed that you will not get the same letter twice. 当您使用random.sample您可以指定想要的项目数量,并确保不会两次收到相同的字母。 There is no such guarantee if you are using random.choice twice. 如果您两次使用random.choice则无法保证。 Of course, if you don't mind it occasionally switching a value with itself (ie nothing happening), then you do not need to change anything. 当然,如果您不介意它偶尔会自己更改一个值(即什么也没有发生),那么您就无需更改任何内容。

Here's how you could use random.sample : 这是使用random.sample

letter1, letter2 = random.sample(copy, 2)

Also, when you are determining the keys to swap 另外,当您确定要交换的密钥时

key1 =  (keys_with_value(copy,letter1))[0]
key2 =  (keys_with_value(copy,letter2))[0]

you are looking for values that match the keys letter1 and letter2 . 您正在寻找与键letter1letter2匹配的值。 If you want letter1 and letter2 to hold values from dictionary1 , you should use 如果要让letter1letter2保留来自dictionary1值,则应使用

letter1, letter2 = random.sample(copy.values(), 2)

Looking at your code some more, it seems to me that your keys_with_values function is entirely unnecessary. keys_with_values一下您的代码,在我看来,您的keys_with_values函数完全没有必要。 Simply finding two random keys and switching their values can be done like this: 只需找到两个随机键并切换其值即可,如下所示:

key1, key2 = random.sample(copy, 2)
copy[key1], copy[key2] = copy[key2], copy[key1]

However, if you really did intend to for letter1 and letter2 to be keys, then you are switching the values of two keys that have values that are also keys. 但是,如果您确实确实希望将letter1letter2键,那么您将切换两个也具有键值的键的值。 In that case, you can use 在这种情况下,您可以使用

key1, key2 = random.sample([k for k, v in copy.items() if v in copy], 2)
copy[key1], copy[key2] = copy[key2], copy[key1]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM