6

在 Pylons webapp 中,我需要使用诸如“<3、45、46、48-51、77”之类的字符串并创建一个整数列表(实际上是对象的 ID)以进行搜索。

关于如何做到这一点的任何建议?我是 Python 的新手,我还没有找到任何可以帮助解决这种事情的东西。

该列表将是: [1, 2, 3, 45, 46, 48, 49, 50, 51, 77]

4

6 回答 6

12

从这里使用 parseIntSet

我也喜欢最后评论中的 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])
于 2009-04-03T03:42:56.123 回答
4

我创建了一个我觉得更易读的@vartec 解决方案版本:

def _parse_range(numbers: str):
    for x in numbers.split(','):
        x = x.strip()
        if x.isdigit():
            yield int(x)
        elif x[0] == '<':
            yield from range(0, int(x[1:]))
        elif '-' in x:
            xr = x.split('-')
            yield from range(int(xr[0].strip()), int(xr[1].strip())+1)
        else:
            raise ValueError(f"Unknown range specified: {x}")

在这个过程中,函数变成了一个生成器:)

于 2019-08-08T12:05:38.230 回答
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
于 2009-04-03T08:24:17.353 回答
0

首先,您需要弄清楚您将接受哪种语法。您当前的示例中有三个:

  1. 单号:45、46

  2. 小于运算符

  3. 短跑范围:48-51

之后,只需将字符串拆分为标记,并检查标记的格式。

于 2009-04-03T03:45:14.747 回答
0

我最近也不得不为一个应用程序做类似的事情。

如果您不需要具体的数字,而只是一种查看给定数字是否在范围内的方法,则可以考虑将其解析为 Python 表达式,您可以将其 eval 为 lambda。例如<3, 5-10, 12可以是func=(lambda x:x<3 or (5 <= x <= 10) or x==12)). 然后你可以调用 lambda,func(11)看看 11 是否属于那里。

于 2009-04-03T08:34:30.697 回答
-1
>>> print range.__doc__
range([start,] stop[, step]) -> list of integers

返回一个包含整数等差数列的列表。range(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]

然后用逗号分割字符串,并为每一位解析它以找出要调用的函数,并将返回的列表连接起来。

还有什么,我会为你写的。

于 2009-04-03T03:56:23.487 回答