Golang通过栈实现表达式运算(中缀表达式转后缀表达式解析语法)

这篇具有很好参考价值的文章主要介绍了Golang通过栈实现表达式运算(中缀表达式转后缀表达式解析语法)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Golang通过栈实现表达式运算(中缀表达式转后缀表达式解析语法)

需求背景:将string表达式数组 [title == AUSU && ( header == Wecome || brand != AC68U )] 解析并使用ES查询得到运算结果。

分析:带有括号的表达式,需要根据优先级解析,可将中缀表达式转换为后缀表达式,去除括号文章来源地址https://www.toymoban.com/news/detail-634966.html

1. 定义栈结构

package scanner_utils

import "errors"

type Stack []interface{}

func (stack Stack) Len() int {
	return len(stack)
}

func (stack Stack) IsEmpty() bool {
	return len(stack) == 0
}

func (stack Stack) Cap() int {
	return cap(stack)
}

func (stack *Stack) Push(value interface{}) {
	*stack = append(*stack, value)
}

func (stack Stack) Top() (interface{}, error) {
	if len(stack) == 0 {
		return nil, errors.New("Stack out of index, len is 0")
	}
	return stack[len(stack)-1], nil
}

func (stack *Stack) Pop() (interface{}, error) {
	theStack := *stack
	if len(theStack) == 0 {
		return nil, errors.New("Stack out of index, len is 0")
	}
	value := theStack[len(theStack)-1]
	*stack = theStack[:len(theStack)-1]
	return value, nil
}

func (stack *Stack) Peek() interface{} {
	theStack := *stack
	value := theStack[len(theStack)-1]
	return value
}

2. 中缀表达式转后缀表达式

// [title==AUSU && ( header==Wecome || brand!=AC68U )] => [title==AUSU header==Wecome brand!=AC68U || &&]
func InfixToSuffixExpression(infixList []string) []string {
	var suffixList []string
	// 符号栈
	stack := Stack{}
	for _, item := range infixList {
		if item != "(" && item != ")" && item != "&&" && item != "||" { // 不是符号,直接添加到数组
			suffixList = append(suffixList, item)
		} else {
			if item == "(" { // 左括号,直接入符号栈
				stack.Push(item)
			} else if item == ")" { // 右括号,将符号栈的运算符弹出,直到遇到左括号
				for {
					if stack.IsEmpty() {
						// 语法错误
						break
					}
					if "(" == stack.Peek().(string) { // 遇到左括号,将左括号弹出,结束循环
						stack.Pop()
						break
					}
					oper, _ := stack.Pop()
					suffixList = append(suffixList, oper.(string))
				}
			} else {
				// item的优先级小于等于符号栈顶元素优先级时,将符号栈顶元素弹出并添加到数组
				// item的优先级大于符号栈顶元素优先级时,将item入栈
				for {
					if stack.IsEmpty() || getPriority(stack.Peek().(string)) < getPriority(item) {
						stack.Push(item)
						break
					}
					oper, _ := stack.Pop()
					suffixList = append(suffixList, oper.(string))
				}
			}
		}

	}

	// 将符号栈剩余的元素依次弹出
	for {
		if stack.IsEmpty() {
			break
		}
		oper, _ := stack.Pop()
		suffixList = append(suffixList, oper.(string))
	}

	return suffixList
}

// 定义优先级
func getPriority(operator string) int {
	OR := 1
	AND := 2

	var resp int
	if operator == "&&" {
		resp = AND
	}

	if operator == "||" {
		resp = OR
	}
	return resp
}

3. 遍历后缀表达式进行运算,并拼接ES查询语法

// 输入参数:[title==AUSU header==Wecome brand!=AC68U || &&]
func jointSearchDsl(suffixExpreList []string) (*elastic.BoolQuery, error) {
	expreStack := scanner_utils.Stack{}

	queryMap := make(map[string]*elastic.BoolQuery)
	index := 1
	var err error
	for _, item := range suffixExpreList {
		if item != "&&" && item != "||" { // 不是运算符,直接入栈
			expreStack.Push(item)
		} else { // 是运算符,弹出栈中两个元素进行计算
			expre1, _ := expreStack.Pop()
			expreStr1 := expre1.(string)
			expre2, _ := expreStack.Pop()
			expreStr2 := expre2.(string)
			// 解析两个表达式的K-V
			kv1BoolQuery := elastic.NewBoolQuery()
			if !strings.HasPrefix(expreStr1, "doneExpre") { // 需要处理
				kv1BoolQuery, err = getExpresDsl(expreStr1)
				if err != nil {
					return nil, err
				}
			} else {
				kv1BoolQuery = queryMap[expreStr1]
			}
			kv2BoolQuery := elastic.NewBoolQuery()
			if !strings.HasPrefix(expreStr2, "doneExpre") { // 需要处理
				kv2BoolQuery, err = getExpresDsl(expreStr2)
				if err != nil {
					return nil, err
				}
			} else {
				kv2BoolQuery = queryMap[expreStr2]
			}

			// 根据运算符使用must或者should拼接
			boolQueryOper := elastic.NewBoolQuery()
			if item == "&&" {
				boolQueryOper.Must(kv1BoolQuery, kv2BoolQuery)
			}
			if item == "||" {
				boolQueryOper.Should(kv1BoolQuery, kv2BoolQuery)
			}

			index++

			// 写一个标识到栈,当作已处理的表达式
			doneExpre := "doneExpre" + strconv.Itoa(index)
			expreStack.Push(doneExpre)
			queryMap[doneExpre] = boolQueryOper
		}
	}

	// 循环结束,取出最后的一个元素,获取对应的boolQuery
	expreN, _ := expreStack.Pop()
	boolQuery := elastic.NewBoolQuery()
	if !strings.HasPrefix(expreN.(string), "doneExpre") {
		boolQuery, err = getExpresDsl(expreN.(string))
		if err != nil {
			return nil, err
		}
	} else {
		boolQuery = queryMap[expreN.(string)]
	}
	return boolQuery, nil
}


// 输入参数:header==Wecome
// 将每一个表达式解析,拼接ES query dsl
func getExpresDsl(expre string) (*elastic.BoolQuery, error) {
    boolQuery := elastic.NewBoolQuery()
    // TODO...
    return boolQuery, nil
}

到了这里,关于Golang通过栈实现表达式运算(中缀表达式转后缀表达式解析语法)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【数据结构与算法】【12】前缀表达式、中缀表达式、后缀表达式

    【数据结构与算法】【12】前缀表达式、中缀表达式、后缀表达式

    什么是前缀表达式、中缀表达式、后缀表达式 前缀表达式、中缀表达式、后缀表达式,是通过树来存储和计算表达式的三种不同方式 以如下公式为例 ( a + ( b − c ) ) ∗ d ( a+(b-c) )*d ( a + ( b − c ) ) ∗ d 通过树来存储该公式,可以表示为 那么问题就来了,树只是一种抽象的数据

    2024年02月08日
    浏览(6)
  • 【数据结构】13:表达式转换(中缀表达式转成后缀表达式)

    【数据结构】13:表达式转换(中缀表达式转成后缀表达式)

    从头到尾依次读取中缀表达式里的每个对象,对不同对象按照不同的情况处理。 如果遇到空格,跳过 如果遇到运算数字,直接输出 如果遇到左括号,压栈 如果遇到右括号,表示括号里的中缀表达式已经扫描完毕,将栈顶的运算符弹出并输出, 直至遇到左括号(左括号出栈

    2024年02月19日
    浏览(6)
  • Java LeetCode篇-深入了解关于栈的经典解法(栈实现:中缀表达式转后缀)

    Java LeetCode篇-深入了解关于栈的经典解法(栈实现:中缀表达式转后缀)

    🔥博客主页: 【 小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍     文章目录         1.0 中缀表达式转后缀说明         1.1 实现中缀表达式转后缀思路         2.0 逆波兰表达式求值         2.1 实现逆波兰表达式求值思路         3.0 有效的括号         3.1 实现有

    2024年02月04日
    浏览(8)
  • 中缀表达式转后缀表达式,使用逆波兰计算。可以计算小数

    中缀表达式转后缀表达式,使用逆波兰计算。可以计算小数

    传递一个分开保存符号与数字的List即可:List SumNumber; 获取参数的构造方法如下: 要求的List保存数据的方式如下: 例如:1+2+3 然后使用 EvaluatePostfixExpressions 方法传递出一个保存好结果的String。

    2024年02月15日
    浏览(13)
  • C++ 数据结构 栈 中缀表达式转后缀表达式并求值

    C++ 数据结构 栈 中缀表达式转后缀表达式并求值

    写在前面,这里用的是我自己写的Stack类,并非STL,实现方法为静态数组,但使用过程中的函数方法一样,无伤大雅。(完整code和Stack_static类赋在最后) 1.从左到右遍历 2.数,即参与运算数,直接放进后缀表达式之后 3.左括号 ,直接压入栈(因为括号的优先级最高,无需判断

    2024年02月03日
    浏览(9)
  • 中缀表达式转后缀表达式看完这一篇文章你就懂了

    一、什么是中缀表达式 二、什么是后缀表达式 三、后缀转中缀具体思路 四、代码实现 中缀表达式就是我们常用的算术表达方式,例如 (12+34)*5 ,运算符在两个数的中间,但是对于中缀表达式来说括号和加减乘除使得问题对于计算机非常复杂,为了有效的处理他们,波兰逻辑

    2024年02月08日
    浏览(5)
  • 【尚硅谷】数据结构和算法——前缀、中缀、后缀表达式规则

    【尚硅谷】数据结构和算法——前缀、中缀、后缀表达式规则

    跟着B站的尚硅谷学习数据结构与算法,语言为java,目前是第七个代码内容——前缀、中缀、后缀表达式 课程传送门:尚硅谷——前缀、中缀、后缀表达式 1)前缀表达式又称波兰式, 前缀表达式 的运算符位于操作符之前。 2)举例说明:(3+4)*5-6 对应的前缀表达式就是 - *

    2024年02月03日
    浏览(9)
  • 262.【华为OD机试真题】符号运算(中缀表达式转逆波兰表达式-Java&Python&C++&JS实现)

    🚀点击这里可直接跳转到本专栏,可查阅顶置最新的华为OD机试宝典~ 本专栏所有题目均包含优质解题思路,高质量解题代码(JavaPythonC++JS分别实现),详细代码讲解,助你深入学习,深度掌握!

    2024年02月21日
    浏览(3)
  • 中缀表达式求值(栈的应用)

    AcWing算法基础课-3302.表达式求值 给定一个表达式,其中运算符仅包含 +,-,*,/ (加 减 乘 整除),可能包含括号,请你求出表达式的最终值。 注意: 数据保证给定的表达式合法。 题目保证符号 - 只作为减号出现,不会作为负号出现,例如, -1+2 , (2+2)*(-(1+1)+2) 之类表达式均不

    2024年02月05日
    浏览(7)
  • 数据结构 | 栈的中缀表达式求值

    数据结构 | 栈的中缀表达式求值

    目录 什么是栈? 栈的基本操作 入栈操作 出栈操作 取栈顶元素 中缀表达式求值 实现思路 具体代码 栈是一种线性数据结构,具有“先进后出”(Last In First Out, LIFO)的特点。它可以看作是一种受限的线性表,只能在表的一端进行插入和删除操作,这一端被称为栈顶,另一端

    2024年02月02日
    浏览(11)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包