高效编码-将简单表达式传递给方法(并对其进行求值) [英] Efficient coding - Pass simple expression to method (and evaluate it)

查看:55
本文介绍了高效编码-将简单表达式传递给方法(并对其进行求值)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好

我正在构建一种方法,我想为其传递(以及其他方式)一个简单的比较表达式:< left_value> < operator> < right_value> ;.
然后,该方法将执行比较并返回结果.

表达式两侧的数据结构可以是double或datetime类型的普通变量或一维数组.如果数据是数组,则将对数组的每个元素求表达式.

我正在考虑将表达式作为文本字符串发送,然后进行解析,或者将表达式作为三个参数(left,op和right)传递.

现在,我的问题是如何在我的方法中组织代码.目前,我仅用一段代码即可对输入的每种可能的变体进行评估.但是,这给了我大量的代码.
2种数据类型* 2种数据结构类型* 2个运算符的侧面*最少6个运算符给出48种可能的组合.这是很多switch/select case语句来处理应该相当简单的事情.

由于我将创建许多采用类似参数的方法,因此,如果我可以更高效地编写代码,将会有很大帮助.我没有将信息传递给方法的任何特定方式,因此所有选项都是打开的.

与往常一样,所有建议都将受到欢迎.

Hello

I''m constructing a method for which I would like to pass (amongst other things) a simple comparison expression: <left_value> <operator> <right_value>.
The method would then perform the comparison and return the result.

The data structure on either side of the expression can be a plain variable or a one-dimensional array, of type double or datetime. If the data is an array, the expression will be evaluated for each element of the array.

I was thinking of sending the expression it as a text string and then parse it, or pass the expression as three arguments (left, op and right).

Now, my problem is how to organize the code in my method. Currently I simply have one piece of code to perform the evaluation for each possible variant of the input. However, this gives me a tremendous amount of code.
2 data types * 2 types of data structures * 2 sides of the operator * minimum 6 operators gives 48 possible combinations. That''s a lot of switch/select case statements to handle something which should be fairly simple.

As I will create many methods taking similar arguments, it would help a lot if I could write the code more efficiently. I am not locked to any particular way of passing the information to the method, so all options are open.

As always, all suggestions are most welcome.

推荐答案

您的方法应特定于任务.因此,如果传递的内容多于表达式,则说明您的方法执行过多.

但是,如果您所有的方法需要是对表达式的求值,则可以执行以下操作:

MyMethod(...,...,...,ProcessExpression(l,op,r),...)

现在,其签名将为ProcessExpression(object l,string op,object r)

首先要做的是如果l.GetType()!= r.GetType()
引发异常
另外,如果它是一个数组,还需要深入研究;如果数组类型不相等,则引发异常.

接下来,您想用两种方法来分解该过程:
InternalProcess(对象l,字符串op,对象r)-AND-
InternalArrayProcess(IList l,字符串op,IList r)

在后面的过程中,您只需要遍历数组中的每个元素并调用InternalProcess(l [index],op,r [index])

您仍然必须按类型执行case语句,但只需要针对在第一个操作数上使用的特定类型执行该操作即可.
your methods should be specific to a task. So if you are passing more than the expression you are doing too much in your method.

But if all your method needs is the evaluation of the expression, you can do something like this:

MyMethod(...,...,..., ProcessExpression(l,op,r),...)

Now the signature for this would be ProcessExpression( object l, string op, object r)

First thing to do is throw an exception if l.GetType() != r.GetType()

Also you need to look deep if it is an array and throw an exception if the array types are not equal.

Next you want to break up the process as two methods:
InternalProcess( object l, string op, object r) -AND-
InternalArrayProcess( IList l, string op, IList r )

Inside the latter process you just are iterating through each element in the array and calling InternalProcess(l[index], op, r[index])

You still have to do a case statement by types but you should only have to do it for the specific types you are working with on the first operand.


首先,感谢您的评论,非常抱歉,我的回复很晚.
在我的项目中,我正在制作自己的自定义数学类,并且目前正在研究数组上简单算术的方法.我需要对数组到数组和数组到变量执行数学运算(+-/*).而且,这正是我的问题所在;我希望能够添加要进行计算的条件.

例子:
假设我有三个阵列; A(10),B(10),C(10),全部加倍.
数组A和B逐个元素地添加,但仅在数组C< C小于1的元素上添加. 1(对于相同的索引号).

另一个例子:
与上面相同,只有B是一个简单变量,而不是数组.然后应在A的所有元素上将B添加到A上,其中C的对应值小于1.

我最初的尝试是将所有这些都整合到一个方法中,在如何执行计算方面给了我太多选择.我的方法为要添加的数组使用了两个参数(A,B),以及条件的表达式.所采用的表达式可以是某种字符串,例如"if C <1",或者理想情况下甚至可以是更复杂的变体. 如果(C + A)/B <B + 1".但是,我发现解析和执行这样的字符串不是一件容易的事(对我来说!),因此我降低了目标,并在方法中添加了另外三个参数.左侧(C),运算符字符串(<")和右侧(1).由于双方都可以是变量或数组,并且数据类型为double或datetime,并且运算符可以为6种类型,所以我在左侧有4种可能(double变量,double数组,datetime变量,datetime数组),右侧有4个,并且有6种运算符类型. 4 * 4 * 6 = 96种可能性(不是我最初发布时误算的48种)

可以将所有代码重载为不同的数据类型(双精度/日期时间)和容器类型(变量/数组),而不是将所有代码都投入一个大方法中,但是这使我需要维护的代码量完全相同.它只是被切碎了.有人可能会说,将所有内容以一种大规模的方法保存起来实际上更简单,因为您可以将所有代码都放在一个地方.如果以后需要更改代码,请确保不要忘记更新任何重载.

我希望实现的一种简化是将运算符作为某种运算符对象传递,可以将其直接包含在数学表达式中(C(i)"op" 1).这在其他语言中也是可能的,例如SAS中的宏编程(如果您曾经与之接触过).在.NET中吗?还是存在其他实现相同效果的方法?

到目前为止,最接近我的解决方案的是创建自己的数据类,然后重载类的运算符以按照我想要的方式执行计算.如果不是将参数传递给此类重载只能通过值而不是引用来完成,那么这实际上将是一个极好的解决方案.测试表明,此类的性能不到使用以引用为参数的方法所能达到的性能的一半.由于其中一些计算会持续数小时和数天,因此将性能降低一半感觉是一个很大的让步.

很抱歉,如果这太冗长,请尝试解释我要实现的目标.
First, thank you for your comments, and sorry for my late reply.
In my project I am making my own custom math class, and I am currently working on methods for simple arithmetics on arrays. I need to perform math operations (+-/*) on array-to-array and array-to-variable. Also, and this is where my question fits; I would like to be able to add conditions on which the calculations will be done.

An example:
Say I have three arrays; A(10), B(10), C(10), all double.
Arrays A and B is to be added element by element, but only on elements where array C < 1 (for the same index number).

Another example:
Same as above, only B is a simple variable and not an array. B should then be added to A on all of A''s elements where the corresponding value of C is less than 1.

My initial attempt was to throw all of this into one method, giving me too many alternatives on how to perform the calculations. My method took two arguments for the arrays to be added (A, B), as well as an expression for the conditions. The expression taken could be some sort of string like "if C < 1", or ideally even more complex variants; "if (C+A)/B < B+1". However, I found that parsing and executing such a string was not a simple task (to me!), so I lowered my aim and put three more arguments in my method; A left side (C), an operator string ("<") and a right side (1). As both sides could be either a variable or an array, and of datatypes double or datetime, and the operator could be of six types, I get 4 possibilities on the left side (double variable, double array, datetime variable, datetime array), 4 on the right side and 6 operator types. 4*4*6 = 96 possibilities (not 48 like I miscalculated in my initial post)

In stead of throwing all the code in one big method, I could overload it for different data types (double/datetime) and container types (variable/array), but that leaves me with exactly the same amount of code to maintain. It''s just chopped up differently. And one could argue that it''s actually simpler to keep it all in one massive method as then you have all the code in one place. If you need to do changes to the code at a later stage, you''re sure you don''t forget to update any of the overloads.

One simplification I was hoping to achieve was to pass the operator as an operator object of some sort, which could be included directly in the mathematical expression ( C(i) ''op'' 1 ). This is possible in other languages like macro programming in SAS (if any of you have been in contact with that). Is it in .NET? Or does there exist some other way of achieving the same effect?

The closest to a solution I''ve gotten so far is to create my own data classes, and then overload the operators of the classes to perform the calculations the way I wanted them. This would actually be an excellent solution, had it not been that passing arguments to such overloads can only be done by value, not by reference. Testing showed that the performance of such a class was less than half of what could be achieved using a method taking a reference as arguments. As some of these calculations will run for hours and days, halving performance feels like a big concession to make.

Sorry if this was too verbose, just trying to explain what I''m trying to achieve.


通常,遇到此类问题时,我会尝试找出解决方法.通过在一个不断变化的虚拟类中解决该问题来完成此操作,直到获得结果为止.

不过,我不认为您需要通过引用传递值.只要您返回所需的特定值,就可以按值传递.

例如,您可以尝试使用仿制药,看看是否可以买到任何东西.并进一步处理过载.

让您的方法成为迭代返回,因此您的IList方法签名会执行大量的Answer< t> .Add(Compute(listA,op,listB))

除此之外,我真的没有时间对这个问题进行更深入的思考.根据我在第一个答案中列出的内容尝试不同的事情,并对其进行扩展,直到获得最佳答案为止.

在我介绍的模型中,使每个调用返回一个值(原始对象类型或数组中的元素),您不必担心如何将数据传递给您.依赖参考值的风险最大,而且很危险.另一方面,通过将答案作为IList返回,可以使调用者灵活地进行以下操作:a)保留原始数组-或者-b)将其中一个数组分配给返回的答案.
Usually what I do when faced with a problem like this is to try and figure out ways of accomplishing this by working it out in a dummy class that I keep changing til I get the results.

What I don''t believe you need, though, is passing values by reference. Passing by value is fine as long as you return the specific values needed.

You could try generics, for example, to see if that buys you anything. And play further with the overloads.

Have your methods become an iterative return so your IList method signature does numerous Answer<t>.Add( Compute( listA, op, listB))

Beyond that, I really don''t have the time to think deeper on this problem. Try different things based on what I listed in my first answer and expand upon it until you get the best answer.

In the model I presented, making each call return a value (either the original object type or an element in an array) you never have to be concerned with how the data is being passed to you. Becoming dependant on reference values is at best risky, and possilbe dangerous. On the other hand, by returning the answer as an IList you give the caller the flexibility to a) leave the original arrays alone -or- b) assign one of the arrays to the answers returned.


这篇关于高效编码-将简单表达式传递给方法(并对其进行求值)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆