【问题标题】:Combination of conditional statements条件语句的组合
【发布时间】:2018-06-06 20:07:26
【问题描述】:

我有 2 组,每组 3 个条件。 设 a,b,c 为一组条件,x,y,z 为另一组。我需要评估以下内容

if(a && x)
..... 
else if(a && y) 
..... 
else if(a && z)
.....

以同样的方式 3 个条件与 b 和 3 与 c。

在不编写所有组合的情况下评估条件的最佳方法是什么?

更新:

我正在使用 Unity 制作游戏。条件 a,b,c 检查球员的 x 位置与球的位置相比是否在一定范围内,条件 x,y,z 对 y 位置。基于正确的条件(从组合 ax、ay、az、bx、by、bz、cx、cy、cz)选择一个动画状态(共 9 个)。所以每个条件都会产生不同的结果。

更新: 我最终制作了两个函数来评估两组条件,每个函数都返回一个枚举,在该枚举上执行按位或以获得最终状态。

【问题讨论】:

  • 条件是否总是循环通过xyz for abc?我在想一些涉及一系列 lambda 表达式的笨拙。比if/else 更难阅读和维护。通常是一个坏主意,除非有超过 9 种组合以及它们之间的代码模式。
  • 我还认为这取决于将在各种条件下执行的操作。如果正在执行的操作之间没有相似之处,为什么不写出所有的组合呢?如果您可以使用相似之处来减少组合,则 OP 需要在问题中添加更多详细信息。
  • 我同意之前的评论,这个问题目前无法回答。如果每个组合都需要特定的代码,那么必须写出所有案例。如果有共同点,它应该是问题的一部分。在提供更多信息之前投票结束。

标签: c# unity3d conditional


【解决方案1】:

这是使用 Linq 表达式的一种方法,Linq 表达式是一种动态定义表达式的方法,您可以在其中对它们执行多项操作。我在这里使用了一个假条件表达式,它以数字作为参数只是为了演示。首先在方法中或直接在代码中定义每个条件。然后将所有这些放入数组中,每个条件设置为一个数组。然后是执行表达式的两个 foreach。

int num = 20;

        ConditionalExpression[] firstSet = { ExpressionA(num), ExpressionB(num), ExpressionC(num) };
        ConditionalExpression[] secondSet = { ExpressionX(num), ExpressionY(num), ExpressionZ(num) };

        foreach(var firstSetExpression in firstSet)
            foreach (var secondSetExpression in secondSet)
            {
                var result1 = Expression.Lambda<Func<bool>>(firstSetExpression.Test).Compile();
                var result2 = Expression.Lambda<Func<bool>>(secondSetExpression.Test).Compile();

                if (result1.Invoke() && result2.Invoke())
                { 
                    // do your thing here 
                }
            }

在方法中为每个条件定义表达式的位置,例如:

private static ConditionalExpression ExpressionA(int num)
        {
             return Expression.Condition(
                          Expression.Constant(num > 10),
                          Expression.Constant("num is greater than 10"),
                          Expression.Constant("num is smaller than 10")
                        );
        }

这甚至可以通过多种方式进行优化,但只是为了让您开始。

更新:这是不喜欢在运行时编译的另一种方式。使用委托:

Func<int, bool>[] firstSet = new Func<int,bool> [] { ExpressionA(), ExpressionA(), ExpressionA() };
            Func<int, bool>[] secondSet = new Func<int, bool>[] { ExpressionA(), ExpressionA(), ExpressionA() };

            foreach(var firstSetExpression in firstSet)
                foreach (var secondSetExpression in secondSet)
                {
                    if (firstSetExpression.Invoke(20) && secondSetExpression.Invoke(20))
                    { 
                        // do your thing here 
                    }
                }
...
...
...

private static Func<int, bool> ExpressionA()
        {
             return (x) => x > 10;
        }

祝你好运。

【讨论】:

  • 在运行时编译?对我来说听起来并不令人兴奋。
【解决方案2】:
  1. 生成所有可能的组合。由于您处理布尔值,因此每个都为您提供 2 个选项。然后 2 个布尔值的最简单可能组合结果为 2 x 2 = 4 个组合。一般而言,K = 2^n,其中 n 表示您处理的布尔数。

如果我是你,我会坚持使用 Tuple&lt;bool, bool, bool&gt; 并嵌套 for(var i = 0; i &lt; 2; i++) 循环(需要 n 个参数 n 个循环)。

  1. 然后我会提供一个Tuple&lt;Predicate&lt;Tuple&lt;bool, bool, bool&gt;&gt;, Action&gt; 列表,它将谓词与回调配对,当谓词等于真时应该触发。

  2. 可以使用 Linq 实现 Rest。类似的东西possibleCombinationsList.Select(tripleOfBooleans =&gt; predicatesAndCallbacksList.Single(predicateAndCallback =&gt; predicateAndCallback.Item1(tripleOfBooleans) == true)).Sinle().Item2();

玩得开心。

【讨论】:

  • 我在 Unity 中执行此操作,但不支持元组。很抱歉之前没有提到这一点。
  • @Shyam 为什么重要?还有一些选项,从 bool[] 开始,到自定义元组类结束。
  • 我最终创建了两个函数来评估两组条件,每个函数都返回一个枚举,在该枚举上执行按位或以获得最终状态。
【解决方案3】:

我的第一个想法是至少先测试第一组条件,然后再测试第二组条件。虽然这不是避免编写所有九个 if 语句的答案,但您平均会减少检查的 if 语句的数量。

if (a) 
{
    if (x) { }
    else if (y) { }
    else if (z) { }
}
else if (b)
{
    if (x) { }
    else if (y) { }
    else if (z) { }
}
else if (c)
{
    if (x) { }
    else if (y) { }
    else if (z) { }
}

【讨论】:

  • @Aominè 我只是在想,如果你写出 OP 开始的模式中的所有组合,验证例如“c”和“z”为真将是第九次验证。在上面使用消除的情况下,它将是第六个。
  • 谢谢。我曾想过这种方法。但是由于重复了 x,y,z 条件,我认为可能有更好的方法来做到这一点。根据其他建议,这似乎是最佳选择。
  • 我最终创建了两个函数来评估两组条件,每个函数都返回一个枚举,在该枚举上执行按位或以获得最终状态。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-28
  • 2018-10-12
  • 2019-05-04
  • 2019-08-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多