2009-04-03 6 views
4

Pylons Webアプリケーションでは、「< 3,45,46,48-51,77」などの文字列を使用して、実際にオブジェクトのIDであるintのリストを作成する必要があります。の検索。Pythonで番号範囲を解釈する

これを行う方法に関する提案はありますか?私はPythonを初めて使いました。この種のことに役立つものは何も見つかりませんでした。

リストは次のようになります[1、2、3、45、46、48、49、50、51、77]

答えて

12

使用parseIntSet here

からIもでpyparsing実装など最後にコメントします。

parseIntSetは "< 3"型エントリを処理し、無効な文字列があればそれを吐き出すためにここで修正されています。

#! /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) 

そしてここでは、サンプルの実行からの出力です:

$ 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]) 
+0

"<3"の機能はありませんが、実際には "1-3"または "0-3"なので追加できる機能です。 +1。 – paxdiablo

+0

"<3"機能をベースラインコードに追加しました。 – paxdiablo

+0

import sysとosが使われていないのはなぜですか? – vartec

0

まず、あなたが受け入れるだろう構文の種類を把握する必要があります。

  1. シングル数:45、範囲内のオペレータより46

  2. 少ない

  3. ダッシュ:現在のあなたの例では3つ持っている48-51

その後に、文字列をトークンに分割し、トークンの形式をチェックするだけです。

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

整数の算術的な進展を含むリストを返します。 範囲(i、j)は[i、i + 1、i + 2、...、j-1]を返します。 start(!)の既定値は0です。 stepが指定されると、増分(または減分)が指定されます。 たとえば、range(4)は[0、1、2、3]を返します。終点は省略されています! これは、4つの要素のリストの正確なインデックスです。

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

あなたのリストを反復して範囲を適切に呼び出すことができると思います。

>>> 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] 

は、次にコンマで文字列を分割し、各ビットのために、リストが返さcatenating、呼び出すために機能するかを把握するのに十分な、それを解析します。

これ以上のものはすべてあなたのために書いたでしょう。

1
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 
0

最近、アプリのために同様のことを行う必要がありました。

具体的な数値は必要ありませんが、与えられた数値が範囲内にあるかどうかを確認する方法として、ラムダに評価できるPython式に解析することを検討してください。例えば、<3, 5-10, 12は、func=(lambda x:x<3 or (5 <= x <= 10) or x==12))とすることができます。それでラムダ、func(11)を呼び出して11がそこに属しているかどうかを調べることができます。

関連する問題