2009-04-03 4 views
4

В pylons webapp мне нужно взять строку, такую ​​как «< 3, 45, 46, 48-51, 77» и создать список ints (которые являются фактически идентификаторами объектов), чтобы Поиск по.Интерпретация номеров в Python

Любые предложения относительно способов сделать это? Я новичок в Python, и я ничего не нашел, что помогает в этом.

Список был бы: [1, 2, 3, 45, 46, 48, 49, 50, 51, 77]

ответ

12

Использование parseIntSet от here

Я также как реализации 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

зачем импортировать sys и os, если они никогда не используются? – vartec

0

Во-первых, вам нужно выяснить, какой синтаксис вы будете принимать. Вы тока имеют три в вашем примере:

  1. Одноместный номер: 45, 46

  2. Менее оператора

  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. Когда задан шаг, он указывает приращение (или декремент). Например, диапазон (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.

Смежные вопросы