简写版本
我正在使用此正则表达式:
(^|[yY]\s{0,}\=|\+|\-)\s{0,}([0-9]{0,}\.?[0-9]{0,})\s{0,}(\*{0,1}[xX]{0,1})\s{0,}(\^{0,1})(-?)([0-9]{0,}\.?[0-9]{0,})(\s{0,}|$)?
要尝试从等式中提取所有元素系数和阶数:
y=x+3.3X^-50+ 15x25.5 - 4x^+2x^2 +3*x-2.5+1.1
我希望正则表达式忽略错误的
4x^
,它丢失了其电源编号(当前不执行此操作),并允许我得出以下最终结果:((1.0, 1.0), (3.3, -50.0), (15.0, 25.5), (2.0, 2.0), (3.0, -3.5), (1.1, 0.0))
第一个坐标是系数,第二个坐标是每个元素的阶数。目前,如果我采用组1&2和5&6分别给我系数和阶数,则“接近”上方的正则表达式有效。
它只是落在错误的
4x^
之上,而且感觉极其不雅,但是我对regex有点陌生,并且不确定要进行哪些改进。我如何改善此正则表达式,并进行修复,以便将
4x^
视为“错误”,但是4x2
和4x^2
都很好?tl;博士版本
我正在尝试解析用户输入的多项式方程,以进行验证,然后将其分解为一系列元素。这些方程式将以字符串形式显示。
这是有关如何要求用户格式化其字符串的示例:
y = 2.0x^2.5 - 3.1x + 5.2
其中
x
是自变量(不是时间符号),而y
是因变量。实际上,用户通常会犯以下任何错误:
y =
*
添加到诸如y = 2.0*x
的系数y = 5x
^
,例如y = x3
但是,对于所有这些,我想说用户尝试编写的内容仍然很容易理解。我的意思是很明显,每个元素的系数和阶数是什么意思。
因此,我想做的是编写一些正则表达式,将输入的字符串正确地拆分为单独的元素,并让我获得每个元素的
A
(系数)和B
(顺序),其中元素的形式通常为Ax^B
和A
, B
可以是任何实数。我设计了以下示例:
y=x+3.3X^-50+ 15x25.5 - 4x^+2x^2 +3*x-2.5+1.1
我相信它涵盖了我上面概述的所有潜在问题,此外还有一个直接错误
4x^+2x^2
缺少元素4x^
上的顺序。对于此示例,我想访问:
((1.0, 1.0), (3.3, -50.0), (15.0, 25.5), (2.0, 2.0), (3.0, -3.5), (1.1, 0.0))
其中4x^
被忽略了。我对regex有点陌生,但是我已经使用regex101.com进行了以下工作:
(^|[yY]\s{0,}\=|\+|\-)\s{0,}([0-9]{0,}\.?[0-9]{0,})\s{0,}(\*{0,1}[xX]{0,1})\s{0,}(\^{0,1})(-?)([0-9]{0,}\.?[0-9]{0,})(\s{0,}|$)?
似乎几乎可以解决以下问题:
4x^
那样捕获丢失的订单-我不确定如何在存在^
的情况下使订单号的可选性“有条件”,而在没有^
但订单号为y = 4x2
的情况下也可以工作另外请注意,我很高兴地忽略了没有求和相同顺序的重复元素的问题,例如我很乐意忽略
y = x^2 + x^2
不会显示为y = 2x^2
。感谢您的任何帮助。
ps用Go编写的程序,但是我在Go上也有点菜鸟,所以我首先用Python进行原型(prototype)设计。不知道这是否会对正则表达式产生任何影响(我真的是正则表达式的新手)。
最佳答案
以下正则表达式主要用于:
(?P<c1>[+-]? *\d+(?:\.\d+)?)? *\*? *[xX] *(?:\^ *(?P<e1>-? *\d+(?:\.\d+)?)|(?P<e2>-? *\d+(?:\.\d+)?)?)|(?P<c2>[+-]? *\d+(?:\.\d+)?)
我之所以这么说,主要是因为该解决方案将“4x ^”的情况视为第1阶,因为要求已经非常宽松,否则尝试忽略该术语会使RE变得更加复杂甚至不可能,因为这会造成歧义用RE解析。
请注意,缺少的系数/指数将不会像您在示例结果中所表示的那样被捕获为“1.0”,这必须在应用正则表达式并将所有空捕获组作为“1”(或对于“0”表示指数取决于捕获的组)。
Here you have the regex in regex101.com用于检查/尝试其工作方式。
这是一个使用golang的工作程序,它可以测试几种情况:
package main
import (
"fmt"
"regexp"
"strconv"
"strings"
)
const e = `(?P<c1>[+-]? *\d+(?:\.\d+)?)? *\*? *[xX] *(?:\^ *(?P<e1>-? *\d+(?:\.\d+)?)|(?P<e2>-? *\d+(?:\.\d+)?)?)|(?P<c2>[+-]? *\d+(?:\.\d+)?)`
var cases = []string{
"y=x+3.3X^-50+ 15x25.5 - 4x^+2x^2 +3*x-2.5+1.1",
"3.3X^-50",
}
func parse(d float64, ss ...string) float64 {
for _, s := range ss {
if s != "" {
c, _ := strconv.ParseFloat(strings.Replace(s, " ", "", -1), 64)
return c
}
}
return d
}
func main() {
re := regexp.MustCompile(e)
for i, c := range cases {
fmt.Printf("testing case %v: %q\n", i, c)
ms := re.FindAllStringSubmatch(c, -1)
if ms == nil {
fmt.Println("no match")
continue
}
for i, m := range ms {
fmt.Printf(" match %v: %q\n", i, m[0])
c := parse(1.0, m[1], m[4])
de := 1.0
if m[4] != "" {
de = 0.0
}
e := parse(de, m[2], m[3])
fmt.Printf(" c: %v\n", c)
fmt.Printf(" e: %v\n", e)
}
}
}
哪个输出:
testing case 0: "y=x+3.3X^-50+ 15x25.5 - 4x^+2x^2 +3*x-2.5+1.1"
match 0: "x"
c: 1
e: 1
match 1: "+3.3X^-50"
c: 3.3
e: -50
match 2: "+ 15x25.5"
c: 15
e: 25.5
match 3: "- 4x"
c: -4
e: 1
match 4: "+2x^2"
c: 2
e: 2
match 5: "+3*x-2.5"
c: 3
e: -2.5
match 6: "+1.1"
c: 1.1
e: 0
testing case 1: "3.3X^-50"
match 0: "3.3X^-50"
c: 3.3
e: -50
Here you have the program on golang playground试试。