协调两个列表
Posted
技术标签:
【中文标题】协调两个列表【英文标题】:Reconcile two lists 【发布时间】:2013-07-17 17:39:33 【问题描述】:所以我有两个不同的列表,需要协调不同的格式和结构。本质上,集合 B 需要匹配集合 A 中的内容,但我想保留集合 B 中现有项目的状态,而不是用集合 A 中的内容覆盖它们。
作为参考,列表实际上并不意味着列表。 “列表”有几种不同的形式,从直接数组到映射。都使用标准迭代器来访问元素。
我通常的处理方式是这样的......
for item in listA
if listB contains item
mark item in list B as visited
else
add item to list b
for item in listB
if visited is true
continue
else
add item to removeList
for item in removeList
remove item from list B
这是可行的,并且是我能想到的唯一真正的方法。我不喜欢我必须做多少次迭代,让三个 for 循环背靠背感觉是错误的。但是,由于我使用的是迭代器,因此在检查列表时无法从列表中删除任何内容,而是必须将它们添加到第三个删除列表中。
在可能的答案中,请记住,速度和内存占用对我来说比编写代码的难易程度更重要。
我的问题真的归结为这一点 - 有没有更好的方法来做到这一点,我没有想到?
我在 C++/C FWIW 中,但我认为任何解决方案都可能与语言无关。
谢谢!
【问题讨论】:
希望“包含”是一个常数或至少 ln time op。您不能立即删除列表 B 中的项目而不是标记为(未)访问然后再次迭代以杀死它的任何原因?通过一些工作,我确定迭代器可以处理这个问题吗? 这是我最关心的问题。我对 STL 迭代器的理解是,底层数据结构在被迭代时不能被触及(就删除或插入而言)。我能想到的任何“修复”都会比迭代删除列表更昂贵——在一般情况下,它会非常小。 我相信在 STL 容器上调用“remove”时,它会为您提供一个新的迭代器,您可以使用它来继续您的横向操作。试试看速度是否加快。 【参考方案1】:这是另一种可能更有效的方法:
removeList = listB
for item in listA
if listB contains item
remove item from removeList
else
add item to listB
for item in removeList
remove item from listB
因此,removeList 不是从零开始构建,而是从所有内容开始,然后从中删除项目。
您还可以通过使用 removeList 存储索引而不是实际项目来提高效率。只要在初始循环中将项目添加到 listB 的末尾,并以相反的顺序删除项目,索引应该仍然有效。
事实上,如果您将 removeList 替换为要保留的布尔值数组,则更简单。所以算法变成了这样:
initialise all itemsToKeep to false
savedListLength = length of listB
for item in listA
offset = find item in listB
if found
mark itemsToKeep[offset] as true
else
add item to listB
for offset from savedListLength-1 down to 0
if itemsToKeep[offset] is false
remove the offset from listB
这避免了最初将任何内容复制到 removeList 中的需要。 itemsToKeep 数组的开销肯定不会比你用来跟踪算法中访问项目的任何东西差。
在某种程度上,最合适的算法可能取决于列表的形式(即向量或链表等),但我确实认为我的方法有可能更有效。
【讨论】:
这比我有的更好吗?将列表 b 复制到 removelist 将导致列表 B 的迭代,您必须迭代 A 和删除列表仍然,所以所有人都告诉您仍在查看相同数量的迭代。 @MotieMediator 这是一个公平的观点,但就代码行而言,它更整洁,这很重要。而且它不需要标记任何我认为也是一个优点的东西。 @MotieMediator 还更新了答案以显示如何修改我的算法以完全摆脱 removeList。以上是关于协调两个列表的主要内容,如果未能解决你的问题,请参考以下文章