您好我正在写一份清单如下:
> l = [[10312, -13.069404602050781], [10313, -28.044403076171875],
> [10314, -32.765602111816406], [10315, -47.353294372558594],
> [10312, -63.069404602050781], [10313, -78.044403076171875],
> [10314, -82.765602111816406], [10315, -97.353294372558594]]
从第3行可以看到列表的第一项重复,我想要实现的是,一旦循环到达maxCount,而不是继续附加在列表的底部,它会附加到对。我最理想的是:
l = [[10312, -13.069404602050781, -63.069404602050781],
[10313, -28.044403076171875, -78.044403076171875],
[10314, -32.765602111816406, -82.765602111816406],
[10315, -47.353294372558594, -97.353294372558594]]
任何想法?
我想出了一个解决方案,但我觉得有点受限,我现在正在使用列表生成器列表,就像这样
table=[]
for k in range(0, len(elementContainer):
k = []
table.append(k)
我认为你是一本字典生成器,但无法使用它,任何帮助,或者你有更好的解决方案。
答案 0 :(得分:1)
如果我不正确的话,这就完成了工作:
l = [[10312, -13.069404602050781], [10313, -28.044403076171875],
[10314, -32.765602111816406], [10315, -47.353294372558594],
[10312, -63.069404602050781], [10313, -78.044403076171875],
[10314, -82.765602111816406], [10315, -97.353294372558594]]
from pprint import pprint
d = {}
for i,(x,n) in enumerate(l):
print i,x,n
if x in d:
l[d[x]].append(n)
del l[i][:]
else:
d[x] = i
l = filter(None,l)
pprint (l)
这是一个更好的算法,因为不再按照l = filter(None,l)
指令对列表进行过滤,因此转换就位。
此指令l = filter(None,l)
创建一个新列表,即在内存中另一个地址的新对象:然后上面的代码没有实现列表的就地转换。
下面的一个执行这样的就地转换,因为通过在处理之前和之后打印列表l
的身份(id est地址)来证明它。
l = [[10312, -13.069404602050781],
[10313, -28.044403076171875],
[10314, -32.765602111816406],
[10312, -63.069404602050781, -55.4444],
[20666, -91, -92, -93, -94],
[10315, -47.353294372558594],
[10314, -82.765602111816406],
[10315, -97.353294372558594],
[10313, -78.044403076171875],
[20666, -40.33, -94, -50.33, -91, -93]
]
from pprint import pprint
d = {}
to_del = []
print 'id(l) before : ',id(l)
pprint (l)
for i,subli in enumerate(l):
if subli[0] in d:
d[subli.pop(0)].extend(subli)
to_del.insert(0,i)
else:
d[subli[0]] = subli
for i in to_del:
del l[i]
print '\nid(l) after : ',id(l)
pprint (l)
请注意,在以前的代码中,d
的值是l
的子列表的索引。
现在在这段新代码中,d
的值直接是l
的子列表。
直接引用对象更加pythonic,而不是通过它们是元素的列表中的索引间接引用它们。
列表to_del
记录第一个循环后将删除的子列表的索引。添加的每个索引都插入to_del
的开头(未附加到其中),以便第二个循环(for i in to_del
)以递归方式通过列表l
,是基于索引删除列表元素时必须遵守的条件。
指令d[subli.pop(0)].extend(subli)
似乎有点难以理解。
操作从执行subli.pop(0)
开始:该指令触发从子列表subli
中提取索引为0的元素并将其返回。
然后d[subli.pop(0)]
将对象 subli.pop(0)作为键提供给d
,同时从子列表subli
中删除此对象。
因此,此时,子列表subli
已缩短其第一个元素,就好像已经执行了指令subli[:] = subli[1:]
,请参阅底部的备注。
接下来,在通过列表d[subli.pop(0)]
的迭代期间l
中先前遇到的子列表l
被扩展,其中元素保留在子列表subli
之后这个被缩短了,也就是说缩短了被1
到len(subli)-1
的元素。但是,由于缩短了subli
,我们只会编写subli
,而不是subli[1:]
。
它有效!结果:
id(l) before : 18732936
[[10312, -13.069404602050781],
[10313, -28.044403076171875],
[10314, -32.765602111816406],
[10312, -63.06940460205078, -55.4444],
[20666, -91, -92, -93, -94],
[10315, -47.353294372558594],
[10314, -82.7656021118164],
[10315, -97.3532943725586],
[10313, -78.04440307617188],
[20666, -40.33, -94, -50.33, -91, -93]]
id(l) after : 18732936
[[10312, -13.069404602050781, -63.06940460205078, -55.4444],
[10313, -28.044403076171875, -78.04440307617188],
[10314, -32.765602111816406, -82.7656021118164],
[20666, -91, -92, -93, -94, -40.33, -94, -50.33, -91, -93],
[10315, -47.353294372558594, -97.3532943725586]]
如果您希望只将非还原元素添加到以前存在的子列表中,则必须是:
for i,subli in enumerate(l):
print 1,subli
if subli[0] in d:
precsubli = d[subli.pop(0)]
precsubli.extend(el for el in subli
if el not in precsubli)
to_del.insert(0,i)
else:
d[subli[0]] = subli
注意区别:
N = [10000,2,3,4]
initial_id = id(N)
print initial_id, N
N = N[1:]
print id(N), N
print '%d==%d : %s' %\
(initial_id, id(N), initial_id==id(N) )
print '------------------'
A = ['HEY','b','c','d']
initial_id = id(A)
print initial_id, A
A[:] = A[1:]
print id(A), A
print '%d==%d : %s' %\
(initial_id, id(A), initial_id==id(A) )
结果
18669480 [10000, 2, 3, 4]
11868480 [2, 3, 4]
18669480==11868480 : False
------------------
18731816 ['HEY', 'b', 'c', 'd']
18731816 ['b', 'c', 'd']
18731816==18731816 : True
这意味着A
就地修改,而N
引用的对象则不是:指令N[1:]
在内存中的某个位置构建一个新对象。 N
引用的对象的位置。