【发布时间】:2019-05-28 08:33:46
【问题描述】:
我有以下代码:
ChangedLinks = set(NewLinkData) - set(OldLinkData)
ReplaceQueue = []
LinkUpdateTokenID = 0
for ChangedLink in ChangedLinks:
for OldLink in OldLinkData:
if ChangedLink[0] is OldLink[0]:
ReplaceStrings = (OldLink[1], "<<LINK UPDATE TOKEN " + str(LinkUpdateTokenID) + ">>", ChangedLink[1])
ReplaceQueue.append(ReplaceStrings)
LinkUpdateTokenID += 1
ChangedLinks 是一组元组,OldLinkData 是一组元组。
随着ChangedLinks 和OldLinkData 的长度增加,该方法的性能明显下降,因为当然有;这只是纯粹的数学!从用户的角度来看,它从有效的瞬时到花费大量时间(尽管不到一秒,至少在我的机器上)。
只有当我可以将OldLinkData 中元组的第一个元素与ChangedLinks 中元组的第一个元素相同的对象匹配时,我才需要向ReplaceQueue 列表添加一个新元素。 (这些元组元素在它们各自的列表中是唯一的,例如,OldLinkData[0][0] 在OldLinkData 的所有其他成员中是唯一的,OldLinkData[1][0] 也是如此,等等。)我能想到的唯一方法是完成这是在上面的代码中循环遍历每个集合/列表并比较元组元素。
有没有更有效的方法来做到这一点?理想情况下,我想要一些方法来快速构建一个列表,其中只有OldLinkData 的成员与ChangedLinks 的一个成员共享他们的第一个元素,顺序与ChangedLinks 相同,这样我就可以比较列表并排。但我不知道如何开始解决这个问题。
编辑:预期输入和输出的一些示例:
OldLinkData: [(<Page.Page object at 0x035AF070>, ']([0])'), (<Page.Page object at 0x043FE4F0>, ']([0, 0])'), (<Page.Page object at 0x043FE590>, ']([0, 0, 0])'), (<Page.Page object at 0x043FE5B0>, ']([0, 1])')]
NewLinkData: [(<Page.Page object at 0x035AF070>, ']([0])'), (<Page.Page object at 0x043FE5B0>, ']([0, 0])'), (<Page.Page object at 0x043FE4F0>, ']([0, 1])'), (<Page.Page object at 0x043FE590>, ']([0, 1, 0])')]
ChangedLinks: {(<Page.Page object at 0x043FE590>, ']([0, 1, 0])'), (<Page.Page object at 0x043FE5B0>, ']([0, 0])'), (<Page.Page object at 0x043FE4F0>, ']([0, 1])')}
ReplaceQueue: [(']([0, 0, 0])', '<<LINK UPDATE TOKEN 0>>', ']([0, 1, 0])'), (']([0, 1])', '<<LINK UPDATE TOKEN 1>>', ']([0, 0])'), (']([0, 0])', '<<LINK UPDATE TOKEN 2>>', ']([0, 1])')]
需要明确的是,这是工作代码中从控制台打印的实际输入和输出。我正在寻找一种比当前代码更有效地实现相同结果的方法。
OldLinkData 和 NewLinkData 中的元组具有以下形式:
(Page.Page object at X, String)
代码的目的是生成ReplaceQueue,这是一个新旧值列表,用于替换一系列字符串(分层笔记本中的页面内容)中的子字符串。 ReplaceQueue 的内容必须缩小到内存中相同的Page.Page 对象在OldLinkData 和NewLinkData 之间有两个不同的关联“链接”(包装在某些降价语法中的整数索引路径的字符串表示)的情况。
OldLinkData和NewLinkData之间的区别是用ChangedLinks作为set(NewLinkData) - set(OldLinkData)获得的,但是我需要在ReplaceQueue中将更改的字符串相互关联。
LinkUpdateTokenID 整数只是一个中间步骤,因此我可以保证 str.replace 的唯一参数,并且不会在两个对象交换链接字符串时搞砸。
编辑:感谢@ParitoshSingh,以下代码明显更快:
def GetLinkData(self):
LinkData = {}
LinkData[id(self.RootPage)] = "](" + self.JSONSerializer.SerializeDataToJSONString(self.RootPage.GetFullIndexPath(), Indent=None) + ")"
self.AddSubPageLinkData(self.RootPage, LinkData)
return LinkData
def AddSubPageLinkData(self, CurrentPage, LinkData):
for SubPage in CurrentPage.SubPages:
LinkData[id(SubPage)] = "](" + self.JSONSerializer.SerializeDataToJSONString(SubPage.GetFullIndexPath(), Indent=None) + ")"
self.AddSubPageLinkData(SubPage, LinkData)
def UpdateLinks(self, OldLinkData, NewLinkData):
ReplaceQueue = []
for PageID in NewLinkData:
if PageID in OldLinkData:
if NewLinkData[PageID] != OldLinkData[PageID]:
ReplaceStrings = (OldLinkData[PageID], "<<LINK UPDATE TOKEN" + str(PageID) + ">>", NewLinkData[PageID])
ReplaceQueue.append(ReplaceStrings)
for ReplaceStrings in ReplaceQueue:
self.SearchWidgetInst.ReplaceAllInNotebook(SearchText=ReplaceStrings[0], ReplaceText=ReplaceStrings[1], MatchCase=True, DelayTextUpdate=True)
for ReplaceStrings in ReplaceQueue:
self.SearchWidgetInst.ReplaceAllInNotebook(SearchText=ReplaceStrings[1], ReplaceText=ReplaceStrings[2], MatchCase=True, DelayTextUpdate=True)
【问题讨论】:
-
请勿使用
is进行比较。使用==。您能否为 oldlinkdata 和 changedlink 粘贴一两个样本并提供预期的输出?只是让每个人都更容易跟进。 -
天哪。我刚刚写完一个解决方案。你的对象是可哈希的吗?
-
你的对象有散列方法吗? Link 这实际上取决于哈希是如何实现的,但理想情况下,哈希不应在对象的生命周期内发生变异,因此任何为同一对象发生变异的部分都不得在其哈希逻辑中。
-
另外,我承认这个问题变得相当棘手。感谢您发布了一个非常好的问题。
-
哦,我想我明白了。不要看用户的角度。那你为什么不使用他们的
id作为哈希呢?如果您使用is运算符并访问相同的值,则它们的 id 必须匹配。
标签: python python-3.x tuples