简体   繁体   English

更好的方法比较列表中的节点

[英]Better way compare nodes in a list

Noob, trying to add 'unique' Nodes to a list, ie with my simple code, I only want the 2 unique nodes, not any duplicate entries.菜鸟,试图将“唯一”节点添加到列表中,即使用我的简单代码,我只想要 2 个唯一节点,而不是任何重复的条目。 I found a poor workaround, where I created a temp list, added the values (as list items, not as nodes) to the temp list if unique, and then added all items from temp to my list of Nodes (converting them to Nodes at that point), but I'm sure there's a better much cleaner way to do this.我发现了一个糟糕的解决方法,我在其中创建了一个临时列表,将值(作为列表项,而不是节点)添加到临时列表中(如果唯一),然后将临时列表中的所有项目添加到我的节点列表中(将它们转换为节点那一点),但我确信有更好更清洁的方法来做到这一点。

class Node():
    # current actor, source, movie
    def __init__(self, state, parent, action):
        self.state = state
        self.parent = parent
        self.action = action

x = Node(5,4,3)
y = Node(5,4,2)
z = Node(5,4,3)

listz = []

if x not in listz:
    listz.append(x)

if y not in listz:
    listz.append(y)

if z not in listz:
    listz.append(z)

for item in listz:
    print(item.state, item.parent, item.action)

Current Outputs (incorrect):
5 4 3
5 4 2 
5 4 3

Should Output (correct):
5 4 3
5 4 2 

Simple solutions I can follow and implement are preferred to clever ones I can't.我可以遵循和实施的简单解决方案优于我不能遵循和实施的聪明解决方案。

you can declare a eq () method in your Node class to easily compare nodes with each in a way you want.您可以在您的Node class 中声明一个eq () 方法,以便以您想要的方式轻松地将节点与每个节点进行比较。

What this does is that everytime you insert a node and call the Not in method, it calls this __eq__ method instead of the default way to compare nodes, and hence is able to detect similar Nodes.这样做的作用是每次插入节点并调用Not in方法时,它都会调用此__eq__方法而不是默认的比较节点的方法,因此能够检测到相似的节点。 What was happening to your original code was that the Not in was just comparing the memory location of all nodes (which are always different)您的原始代码发生的事情是Not in只是比较所有节点的 memory 位置(它们总是不同的)

For example,例如,

class Node():
    # current actor, source, movie
    def __init__(self, state, parent, action):
        self.state = state
        self.parent = parent
        self.action = action
    def __eq__(self, b):
        return (self.state == b.state) and (self.parent == b.parent) and (self.action == b.action)

x = Node(5,4,3)
y = Node(5,4,2)
z = Node(5,4,3)

listz = []

if x not in listz:
    listz.append(x)

if y not in listz:
    listz.append(y)

if z not in listz:
    listz.append(z)

for item in listz:
    print(item.state, item.parent, item.action)

What you're describing is an ordered set, which Python does not natively support, but which you can emulate with keys of a dict, which is guaranteed to maintain insertion order since Python 3.7 (or you can use collections.OrderedDict for prior versions). What you're describing is an ordered set, which Python does not natively support, but which you can emulate with keys of a dict, which is guaranteed to maintain insertion order since Python 3.7 (or you can use collections.OrderedDict for prior versions) .

To make two Node objects with the same attribute values recognized as identical as keys of a dict, however, you should define both the __hash__ and __eq__ methods with the hash from a tuple of the relevant attributes:但是,要使具有相同属性值的两个Node对象被识别为与 dict 的键相同,您应该使用 hash 从相关属性的元组中定义__hash____eq__方法:

class Node():
    def __init__(self, state, parent, action):
        self.state = state
        self.parent = parent
        self.action = action
    def __hash__(self):
        return hash((self.state, self.parent, self.action))
        # you can also use the following instead if don't want to hard-code attributes:
        # return hash(tuple(vars(self).values()))
    def __eq__(self, other):
        return hash(self) == hash(other)

so that:以便:

x = Node(5,4,3)
y = Node(5,4,2)
z = Node(5,4,3)

listz = {}
for item in x, y, z:
    listz[item] = None

for item in listz:
    print(item.state, item.parent, item.action)

outputs:输出:

5 4 3
5 4 2

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

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