Interpretation von Zahlenbereichen in Python

In einem Pylons webapp muss ich einen String wie "<3, 45, 46, 48-51, 77" nehmen und eine Liste von Ints erstellen (die eigentlich IDs von Objekten sind), um zu suchen.

Irgendwelche Vorschläge auf Möglichkeiten, dies zu tun? Ich bin neu in Python, und ich habe nichts da draußen gefunden, das mit dieser Art von Dingen hilft.

Die Liste wäre: [1, 2, 3, 45, 46, 48, 49, 50, 51, 77]

5 Solutions collect form web for “Interpretation von Zahlenbereichen in Python”

Verwenden Sie parseIntSet von hier aus

Ich mag auch die pyparsing Umsetzung in den Kommentaren am Ende.

Das parseIntSet wurde hier geändert, um "<3" -Typ-Einträge zu behandeln und nur die ungültigen Zeichenfolgen auszuspucken, falls es irgendwelche gibt.

#! /usr/local/bin/python import sys import os # return a set of selected values when a string in the form: # 1-4,6 # would return: # 1,2,3,4,6 # as expected... def parseIntSet(nputstr=""): selection = set() invalid = set() # tokens are comma seperated values tokens = [x.strip() for x in nputstr.split(',')] for i in tokens: if len(i) > 0: if i[:1] == "<": i = "1-%s"%(i[1:]) try: # typically tokens are plain old integers selection.add(int(i)) except: # if not, then it might be a range try: token = [int(k.strip()) for k in i.split('-')] if len(token) > 1: token.sort() # we have items seperated by a dash # try to build a valid range first = token[0] last = token[len(token)-1] for x in range(first, last+1): selection.add(x) except: # not an int and not a range... invalid.add(i) # Report invalid tokens before returning valid selection if len(invalid) > 0: print "Invalid set: " + str(invalid) return selection # end parseIntSet print 'Generate a list of selected items!' nputstr = raw_input('Enter a list of items: ') selection = parseIntSet(nputstr) print 'Your selection is: ' print str(selection) 

Und hier ist die Ausgabe aus der Probe laufen:

 $ python qq.py Generate a list of selected items! Enter a list of items: <3, 45, 46, 48-51, 77 Your selection is: set([1, 2, 3, 45, 46, 77, 48, 49, 50, 51]) 
 rng = "<3, 45, 46, 48-51, 77" ids = [] for x in map(str.strip,rng.split(',')): if x.isdigit(): ids.append(int(x)) continue if x[0] == '<': ids.extend(range(1,int(x[1:])+1)) continue if '-' in x: xr = map(str.strip,x.split('-')) ids.extend(range(int(xr[0]),int(xr[1])+1)) continue else: raise Exception, 'unknown range type: "%s"'%x 

Zuerst musst du herausfinden, welche Art von Syntax du akzeptierst. Sie haben derzeit drei in Ihrem Beispiel:

  1. Einzelzahl: 45, 46

  2. Weniger als Betreiber

  3. Dash: 48-51

Danach geht es nur darum, die Saite in Token zu spalten und das Format des Tokens zu überprüfen.

 >>> print range.__doc__ range([start,] stop[, step]) -> list of integers 

Geben Sie eine Liste mit einer arithmetischen Progression von Ganzzahlen zurück. Bereich (i, j) liefert [i, i + 1, i + 2, …, j-1]; Start (!) Ist standardmäßig auf 0 gesetzt. Wenn Schritt gegeben ist, gibt es das Inkrement (oder Dekrement) an. Beispielsweise gibt der Bereich (4) [0, 1, 2, 3] zurück. Der Endpunkt wird weggelassen! Dies sind genau die gültigen Indizes für eine Liste von 4 Elementen.

 >>> range(33,44) [33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43] >>> range(1,3) [1, 2] 

Ich stelle mir vor, dass Sie Ihre Liste iterieren können, und rufen Sie ordnungsgemäß an.

 >>> def lessThan(n) : ... return range(n+1) ... >>> lessThan(4) [0, 1, 2, 3, 4] >>> def toFrom(n,m): ... return range(n,m) ... >>> toFrom(33,44) [33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43] 

Dann teilen Sie die Zeichenfolge auf Kommas, und für jedes Bit, parsen Sie es genug, um herauszufinden, welche Funktion zu rufen, Ketten der Listen zurückgegeben.

Noch mehr und ich hätte es für dich geschrieben.

Ich musste auch in letzter Zeit etwas Ähnliches für eine App machen.

Wenn du keine konkreten Zahlen brauchst, sondern nur einen Weg, um zu sehen, ob eine gegebene Zahl im Bereich ist, könntest du es in Erwägung ziehen, es zu einem Python-Ausdruck zu analysieren, den du in ein Lambda verwandeln kannst. Zum Beispiel könnte <3, 5-10, 12 func=(lambda x:x<3 or (5 <= x <= 10) or x==12)) . Dann kannst du einfach die Lambda anrufen, func(11) zu sehen, ob 11 dort func(11) .

Python ist die beste Programmiersprache der Welt.