我的问题是在循环中管理插入/追加方法。
我有两个长度为N
的列表:第一个列表(我们称之为s
)表示其中的子集,而第二个表示我想要的数量x
评估。为简单起见,我们假设每个子集都呈现T个元素。
cont = 0;
for i in range(NSUBSETS):
for j in range(T):
subcont = 0;
if (x[(i*T)+j] < 100):
s.insert(((i+1)*T)+cont, s[(i*T)+j+cont]);
x.insert(((i+1)*T)+cont, x[(i*T)+j+cont]);
subcont += 1;
cont += subcont;
当循环遍历两个列表的所有元素时,我希望当满足某个条件时(例如x[i] < 100
),该元素的副本放在子集的末尾,并且然后继续循环,直到完成子集的所有原始成员的分析。保持“顺序”很重要,即在元素的最后一个元素旁边插入元素。
我认为一种方法可能是在2个计数器变量中存储子集和全局内的副本数量(参见代码):这样,我可以根据以下方式移动我正在查看的元素的索引那。我想知道是否存在一些更简单的方法,可能使用一些Python魔法。
答案 0 :(得分:2)
如果想要将额外副本插入列表而不制作整个列表的完整副本,则可以使用generator expression进行尝试。在循环浏览列表时,收集要添加的匹配项。在处理每个项目时产生,然后产生每个收集的项目。
这是一个只有一个列表的简化示例,但希望它能说明这个想法。如果你喜欢我已经完成并且通过理解扩展了生成器,你只会得到一份副本。如果您只想存储或进一步分析已处理的列表(例如,将其写入磁盘),则根本无法将其存储在内存中。
def append_matches(input_list, start, end, predicate):
# where predicate is a filter function or lambda
for item in input_list[start:end]:
yield item
for item in filter(predicate, input_list[start:end]):
yield item
example = lambda p: p < 100
data = [1,2,3,101,102,103,4,5,6,104,105,106]
print [k for k in append_matches (data, 0, 6, example)]
print [k for k in append_matches (data, 5, 11, example)]
[1, 2, 3, 101, 102, 103, 1, 2, 3]
[103, 4, 5, 6, 104, 105, 4, 5, 6]
答案 1 :(得分:2)
我猜你不想复制列表的愿望是基于你的C背景 - 假设它会更昂贵。在Python中,列表实际上不是列表,插入有O(n)时间,因为它们更像是向量,因此那些插入操作都是复制列表。
使用额外元素构建新副本比尝试就地更新更有效。如果你真的想要这样做,你需要编写一个包含prev / next引用的LinkedList类,这样你的Python代码才真正是C方法的副本。
最Pythonic方法不会尝试进行就地更新,因为使用值而不是引用来表达您想要的内容更简单:
def expand(origLs) :
subsets = [ origLs[i*T:(i+1)*T] for i in range(NSUBSETS) ]
result = []
for s in subsets :
copies = [ e for e in s if e<100 ]
result += s + copies
return result
要记住的主要事情是,解释的垃圾收集语言的基础成本模型与C非常不同。并非所有复制操作实际上都会导致数据移动,并且无法保证尝试重用相同的内存将会成功或更有效率。唯一真正的答案是在您的真实问题上尝试这两种技术并分析结果。
答案 2 :(得分:0)
我倾向于复制您的列表,然后在循环原件时,当您遇到插入标准时插入您需要它的位置的副本。然后,您可以输出复制和更新的列表。
答案 3 :(得分:0)
我认为找到了一个简单的解决方案。 我从最后一个子集向后循环,将副本放在每个子集的末尾。这样,我避免遇到“新”元素并摆脱计数器和 similia 。
for i in range(NSUBSETS-1, -1, -1):
for j in range(T-1, -1, -1):
if (x[(i*T)+j] < 100):
s.insert(((i+1)*T), s[(i*T)+j])
x.insert(((i+1)*T), x[(i*T)+j])
答案 4 :(得分:-1)
一种可能性是使用numpy的高级索引,通过构建原始列表的“复制”索引列表,并将其添加到代表每个索引的每个索引/切片列表,提供将元素复制到子集末尾的错觉。子集。然后你将最后的所有索引/切片列表组合在一起,并使用最终的索引列表来访问你的所有项目(我相信也有支持这样做的生成器风格,你可能会发现它有用作高级索引/切片返回副本而不是视图)。根据要复制的标准的元素数量,这应该是相当有效的,因为每个子集将其索引作为切片对象,减少了跟踪所需的索引数量。