首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何排除python中的一组字符

如何排除python中的一组字符
EN

Stack Overflow用户
提问于 2019-09-22 10:12:52
回答 4查看 1.1K关注 0票数 1

我想要写一个脚本,返回功率为1的数字。用户的输入是二次和正常数字。我想要的是以下内容:

代码语言:javascript
运行
复制
input = "+2**5+3+4**8-7"
Output = "3,-7"

我尝试了regex re.findall(r"[+-]?[0-9]+[^[*][*][2]]", input),但它没有工作,这在预先感谢:)

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2019-09-22 10:15:11

您需要一个负面的四周断言,并添加边界锚:

代码语言:javascript
运行
复制
r'(?<!\*\*)-?\b\d+\b(?!\*\*)'

(?<!...)语法仅在文本与模式不匹配的位置匹配。类似地,(?!...)语法对于下面的文本也是如此。它们一起确保您只匹配不是指数(跟随**)且没有指数(后面跟着**)的数字。

\b边界锚点仅在字符串的开头或结尾匹配,在任何地方都有一个单词字符后面跟着一个非单词字符,反之亦然(在\w\W\W\w之间,\w愉快地包含数字,而不是算术字符):

代码语言:javascript
运行
复制
>>> import re
>>> input = "+2**5+3+4**8-7"
>>> re.findall(r'(?<!\*\*)-?\b\d+\b(?!\*\*)', input)
['3', '-7']

请注意,我使用\d来匹配数字,并从模式中删除了+,因为您不希望在预期的输出中这样做。

您可以在在线regex101演示中使用表达式;例如,您可以在数字> 10的情况下尝试该表达式,并使用单个*进行乘法。

如果您必须支持负指数,那么上面的内容是不够的,因为如果没有数字前面的...**-42,则42匹配。在这种情况下,需要在不允许-?**-之前进行额外的负面观察:

代码语言:javascript
运行
复制
r'(?<!\*\*)-?(?<!\*\*-)\b\d+\b(?!\*\*)'

(感谢卡西米尔提出了我的观点,并提出了解决方案)。

但是,在这一点上,我建议您切换到将表达式解析为抽象语法树,然后遍历树来提取不属于指数的操作数:

代码语言:javascript
运行
复制
import ast

class NumberExtractor(ast.NodeVisitor):
    def __init__(self):
        self.reset()

    def reset(self):
        self.numbers = []

    def _handle_number(self, node):
        if isinstance(node, ast.Constant):
            if isinstance(node.value, (int, float, complex)):
                return node.value
        elif isinstance(node, ast.Num):
            return node.n

    def visit_UnaryOp(self, node):
        if isinstance(node.op, (ast.UAdd, ast.USub)):
            operand = self._handle_number(node.operand)
            if operand is None:
                return
            elif isinstance(node.op, UAdd):
                self.numbers.append(+operand)
            else:
                self.numbers.add(-operand)

    def visit_Constant(self, node):
        if isinstance(node.value, (int, float, complex)):
            self.numbers.append(node.value)

    def visit_Num(self, node):
        self.numbers.append(node.n)

    def visit_BinOp(self, node):
        if isinstance(node.op, ast.Pow):
            return  # ignore exponentiation
        self.generic_visit(node)  # process the rest

def extract(expression):
    try:
        tree = ast.parse(expression, mode='eval')
    except SyntaxError:
        return []
    extractor = NumberExtractor()
    extractor.visit(tree)
    return extractor.numbers

这只提取数字;减法不会产生负数:

代码语言:javascript
运行
复制
>>> input = "+2**5+3+4**8-7"
>>> extract(input)
[3, 7]

此外,它可以处理任意数量的空白,以及比正则表达式更复杂的表达式:

代码语言:javascript
运行
复制
>>> extract("(10 + 15) * 41 ** (11 + 19 * 17) - 42")
[10, 15, 42]
票数 3
EN

Stack Overflow用户

发布于 2019-09-22 10:15:00

代码语言:javascript
运行
复制
re.findall(r"(?<!\*\*)(?<!\*\*[+-])[+-]?\b[0-9]++(?!\*\*)", input)

(?!\*\*)是一个负前瞻,确保我们没有2位数后的*

re不支持隐性量词,您必须使用PyPi正则表达式

演示

票数 2
EN

Stack Overflow用户

发布于 2019-09-22 11:08:05

您可以编写一个解析器并检查所需的任何内容。我知道它有点长,但很有趣:)

代码语言:javascript
运行
复制
$ cat lexer.py
import re
from collections import namedtuple

tokens = [
    r'(?P<TIMES>\*)',
    r'(?P<POW>(\+|-)?\d+\*\*\d+)',
    r'(?P<NUM>(\+|-)?\d+)'
    ]

master_re = re.compile('|'.join(tokens))
Token = namedtuple('Token', ['type','value'])
def tokenize(text):
    scan = master_re.scanner(text)
    return (Token(m.lastgroup, m.group())
            for m in iter(scan.match, None))

x = '+2**5+3+4**8-7'

required = []
for tok in tokenize(x):
  if tok.type == 'POW':
      coeff, exp = tok.value.split('**')
      if exp == '1':
          required.append(coeff)
  elif tok.type == 'NUM':
      required.append(tok.value)

print(required)

输出:

代码语言:javascript
运行
复制
$ python lexer.py
['+3', '-7']
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58048173

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档