列表清单:使用一个作业更改所有参考文献?

时间:2015-07-03 01:20:30

标签: python

基本原理:我启动一个包含多个堆的列表的脚本。在每一步,我都想加入"堆,但保持两个连接的索引指向同一个元素。

简而言之,给定一个可变元素列表,list[a] is list[b]返回True,如何在保留list[a] = [new]list[a]的同时分配(list[b])引用同一个可变容器?

因此,例如,如果每个堆都由一个字母表示,我们就有

t is ['a', 'b', 'c', 'd']
t is ['ac', 'b', 'ac', 'd'] (0 and 2 merge)
t is ['abc', 'abc', 'abc', 'd'] (0 and 1 merge, but since 0 also refers to 2, it is as if 0/2 and 1 merged... into 0/1/2)

在这个阶段,如果我做了set(map(id, t)),我希望它只有两个元素。

我的问题是我似乎无法直接影响被指向的对象,因此我必须迭代整个列表,挑选出与合并索引匹配的任何ID,并直接分配。

有没有办法改变底层对象而不是指向它的所有指针?

所需行为的完整示例:

>>> my_list = [['a'], ['b'], ['c']]
>>> merge(my_list, 0, 2) # mutates, returns None
>>> my_list
[['a', 'c'], ['b'], ['a', 'c']]
>>> my_list[0] is my_list[2]
True
>>> merge(my_list, 0, 1)
>>> my_list
[['a', 'c', 'b'], ['a', 'c', 'b'], ['a', 'c', 'b']]
>>> my_list[0] is my_list[1]
True
>>> my_list[1] is my_list[2]
True

问题是,如果在merge范围内,我只需致电

my_list[arg1] = my_list[arg2] = my_list[arg1]+my_list[arg2]

它仅影响arg1arg2的条目。我希望它影响可能指向my_list[arg1]my_list[arg2]元素的任何其他条目,以便最终my_list只是指向同一个大堆的指针的集合,吸收了所有小孩子。

3 个答案:

答案 0 :(得分:1)

这就像你要得到的那样接近:

def merge(primary, first, second):
    primary[first] += primary[second]
    primary[second] = primary[first]

first = ['a']
second = ['b']
third = ['c']

main = [first, second, third]
print(main)
merge(main, 0, 2)
print(main)
assert main[0] is main[2]
merge(main, 0, 1)
print(main)
assert main[1] is main[2]
print(first, second, third)

和打印输出:

[['a'], ['b'], ['c']]
[['a', 'c'], ['b'], ['a', 'c']]
[['a', 'c', 'b'], ['a', 'c', 'b'], ['a', 'c', 'b']]
(['a', 'c', 'b'], ['b'], ['c'])

如您所见,列表元素最终都是同一个对象,但进入主列表的列表不是。

修改

不幸的是,如果您不在每个合并中包含第一个列表元素,这也会失败。

所以这里没有捷径。如果您希望每个元素都是相同的元素,或者只是相等,那么您将不得不遍历列表以完成它:

def merge(primary, first, second):
    targets = primary[first], primary[second]
    result = primary[first] + primary[second]
    for index, item in enumerate(primary):
        if item in targets:
            primary[index] = result

答案 1 :(得分:1)

链分配:

>>> my_list = [['a'], ['b'], ['c']]

>>> my_list[0] = my_list[2] = my_list[0]+my_list[2]

>>> my_list
[['a', 'c'], ['b'], ['a', 'c']]

>>> my_list[0] += [1,2,3]

>>> my_list
[['a', 'c', 1, 2, 3], ['b'], ['a', 'c', 1, 2, 3]]

>>>

如果您先a=c=a+c,则会产生a==c==_list_object_001;当你执行a=b=a+b第二次时,会产生a==b==_list_object_002,所以它出错了 如果您不处理作业顺序,即使使用pointer,也无法执行此操作。我认为你应该保留一张地图以使事情正确。

答案 2 :(得分:1)

据我所知,我不认为使用python列表的可变性可以做到这一点。如果你有元素X和Y,这两个元素已经是其他元素的合并,并且你想合并它们,列表可变性将无法将更改发送给双方。您可以使X,Y和指向与X相同的对象的所有元素相同,或者您可以使X,Y和指向与Y相同的对象的所有元素相同,但不能同时使用。

我认为最好的办法是定义一个自定义对象来表示元素,这些元素具有父节点和最终父节点的概念。

class Nodes(object):
    def __init__(self, input1):
        self.parent = None
        self.val = [input1]

    def ultimate_parent(self):
        if self.parent:
            return self.parent.ultimate_parent()
        else:
            return self

    def merge(self, child):
        self.ultimate_parent().val += child.ultimate_parent().val
        child.ultimate_parent().parent = self.ultimate_parent()

    def __repr__(self):
        return str(self.ultimate_parent().val)

def merge(node_list, i, j):
    node_list[i].merge(node_list[j])


list1 = [Nodes(x) for x in 'abcd']
print list1

merge(list1, 0, 2)
print list1
merge(list1, 1, 3)
print list1
merge(list1, 0, 1)
print list1

这将输出:

[['a', 'c'],['b'],['a', 'c'],['d']]
[['a', 'c'],['b', 'd'],['a', 'c'],['b', 'd']]
[['a', 'c', 'b', 'd'],['a', 'c', 'b', 'd'],['a', 'c', 'b', 'd'],['a', 'c', 'b', 'd']]