I have the following code:
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
is a set of tuples, and OldLinkData
is a list of tuples.
There is a noticeable dip in the performance of the method this is in as the lengths of ChangedLinks
and OldLinkData
increase, because of course there is; that's just sheer math! It goes from effectively instantaneous from the user perspective to taking a noticeable amount of time (though less than a second, at least on my machine).
I need to add a new element to the ReplaceQueue
list only when I can match the first element of a tuple in OldLinkData
as the same object as the first element of a tuple in ChangedLinks
. (These tuple elements are unique within their respective lists, as in, OldLinkData[0][0]
is unique among all other members of OldLinkData
, and the same for OldLinkData[1][0]
, and so on.) The only way I can think of to accomplish this is to loop through each set/list as in the code above and compare the tuple elements.
Is there a more efficient way to do this? Ideally I'd like some way to quickly construct a list of only the members of OldLinkData
which share their first element with one of the members of ChangedLinks
, in the same order as ChangedLinks
, so that I can just compare the lists side-by-side. But I have no idea how to begin solving this issue.
Edit: Some examples of expected input and output:
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])')]
To be clear, this is actual input and output as printed from the console in the working code. I'm looking for a way to achieve this same result more efficiently than the current code.
The tuples in OldLinkData
and NewLinkData
are of the form:
(Page.Page object at X, String)
The purpose of the code is to produce ReplaceQueue
, a list of old and new values for replacing substrings throughout a series of strings (the page contents in a hierarchical notebook). ReplaceQueue
's content has to be narrowed to cases where the same Page.Page
object in memory has two different associated "links" (string representations of integer index paths wrapped in some markdown syntax) across OldLinkData
and NewLinkData
.
The difference between OldLinkData
and NewLinkData
is obtained with ChangedLinks
as set(NewLinkData) - set(OldLinkData)
, but then I need to associate the changed strings with each other in ReplaceQueue
.
The LinkUpdateTokenID
integer is just an intermediate step so that I can guarantee unique parameters for str.replace
and not muck things up when two objects swap link strings.
Edit: Thanks to @ParitoshSingh, the following code is noticeably faster:
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)