Hier ist ein schneller Ersatz für RevisionSet, die es zu einem Satz macht. Es sollte viel schneller sein. Ich habe es nicht vollständig getestet, aber es hat mit allen Tests funktioniert, die ich gemacht habe. Es gibt zweifellos andere Möglichkeiten, die Dinge zu beschleunigen, aber ich denke, dass dies wirklich helfen wird, weil es die schnelle Implementierung von Mengen nutzt, anstatt Schleifen in Python zu machen, die der ursprüngliche Code in Funktionen wie __sub__
und __and__
tat. Das einzige Problem ist, dass der Iterator nicht sortiert ist.Möglicherweise müssen Sie ein wenig Code ändern, um dies zu berücksichtigen. Ich bin sicher, es gibt andere Möglichkeiten, dies zu verbessern, aber hoffentlich wird es Ihnen einen guten Start geben.
class RevisionSet(set):
"""
A set of revisions, held in dictionary form for easy manipulation. If we
were to rewrite this script for Python 2.3+, we would subclass this from
set (or UserSet). As this class does not include branch
information, it's assumed that one instance will be used per
branch.
"""
def __init__(self, parm):
"""Constructs a RevisionSet from a string in property form, or from
a dictionary whose keys are the revisions. Raises ValueError if the
input string is invalid."""
revision_range_split_re = re.compile('[-:]')
if isinstance(parm, set):
print "1"
self.update(parm.copy())
elif isinstance(parm, list):
self.update(set(parm))
else:
parm = parm.strip()
if parm:
for R in parm.split(","):
rev_or_revs = re.split(revision_range_split_re, R)
if len(rev_or_revs) == 1:
self.add(int(rev_or_revs[0]))
elif len(rev_or_revs) == 2:
self.update(set(range(int(rev_or_revs[0]),
int(rev_or_revs[1])+1)))
else:
raise ValueError, 'Ill formatted revision range: ' + R
def sorted(self):
return sorted(self)
def normalized(self):
"""Returns a normalized version of the revision set, which is an
ordered list of couples (start,end), with the minimum number of
intervals."""
revnums = sorted(self)
revnums.reverse()
ret = []
while revnums:
s = e = revnums.pop()
while revnums and revnums[-1] in (e, e+1):
e = revnums.pop()
ret.append((s, e))
return ret
def __str__(self):
"""Convert the revision set to a string, using its normalized form."""
L = []
for s,e in self.normalized():
if s == e:
L.append(str(s))
else:
L.append(str(s) + "-" + str(e))
return ",".join(L)
Zusatz: By the way, ich verglichenen Gewerkschaften, Kreuzungen und Subtraktionen des ursprünglichen RevisionSet und meinen RevisionSet oben zu tun, und der obige Code ist aus 3x für diese Vorgänge schneller 7x, wenn sie auf zwei Betrieb RevisionSets mit 75000 Elementen. Ich weiß, dass andere Leute sagen, dass numpy der richtige Weg ist, aber wenn du mit Python nicht sehr erfahren bist, wie dein Kommentar zeigt, dann möchtest du diesen Weg vielleicht nicht gehen, weil er viel mehr Änderungen beinhalten wird. Ich würde empfehlen, meinen Code zu testen, um zu sehen, ob er funktioniert, und wenn ja, dann sehen Sie, ob er schnell genug für Sie ist. Wenn dies nicht der Fall ist, würde ich versuchen, ein Profil zu erstellen, um zu sehen, was verbessert werden muss. Nur dann würde ich in Betracht ziehen, numpy zu verwenden (was ein sehr gutes Paket ist, das ich ziemlich häufig benutze).
Welche Operationen möchten Sie in der Booleschen Liste durchführen? Würde Ihnen eine Reihe von Booleans helfen? – eumiro
Diese Set-Implementierung sieht aus wie O (n), nicht O (n * m). 'if r in rs', wo' rs' ein dict ist, ist eine O (1) -Operation, nicht O (len (rs)). –
@Baffe Boyois - wahr, kommen Sie, um darüber nachzudenken. Der Fragetext wurde korrigiert. –