我如何制作类似switch语句的东西,但是对于多种条件

时间:2017-09-21 16:16:08

标签: c#

private bool test(int x, int y, int z)
{
    int[] arr = {x,y,z};
    switch (arr)
    {
        case {4,5,6}:
            return true;
        case {1,2,3}:
            return true;
        case {7,8,9}:
            return true;
        default:
            return false;
    }
}

基本上,我想创建一个执行此操作的函数。但是,您不能在switch语句中使用数组值。我将如何完成这样的事情?我真的不想做一堆if语句,大约有300种可能的组合。

为了进一步说明,如果找到一个案例,该函数将始终返回true,如果找不到案例,则返回false。 (订单很重要)

一种可能的解决方案是将x y z值转换为字符串,“x y z”然后具有~300字符串值的大小写。但这看起来很糟糕。

2 个答案:

答案 0 :(得分:4)

使用HashSet来促进有效组合。然后使用x,y,z搜索其中的给定Contains组合,并且因为它是HashSet需要O(1)

HashSet<(int a, int b, int c)> options = new HashSet<(int a, int b, int c)>
{
    (4,5,6),
    (1,2,3),
    (7,8,9),
    // ... the rest of the cases
};

options.Contains((x, y, z));

对于C#7.0之前的使用:

HashSet<Tuple<int, int, int>> options = new HashSet<Tuple<int, int, int>>
{
    Tuple.Create(4,5,6),
    Tuple.Create(1,2,3),
};

options.Contains(Tuple.Create(x, y, z));

请注意,300个硬编码案例(或任何硬编码案例)不是一个好习惯。我建议重新考虑如何存储这些值。您可以将它们存储在数据库或配置文件中并加载它们。然后按照我的建议在HashSet中加载商店。

至于switch case通知,如果您对不同的案例有相同的行为,您可以:

switch (caseSwitch) {
    case 1:
    case 2:
    case 3:
    case 4:
        return true;
    default:
        return false;
}

答案 1 :(得分:0)

鉴于x上的范围,yz被限制为适合每个字节,您可以将所有三个包装成24位的32位整数并减少解决方案的内存占用量。 Ints是值类型(与Tuple不同),因此在结构中或查找期间不需要额外的堆分配。

internal sealed class MembershipSet
{
    private readonly HashSet<int> _members = new HashSet<int>();

    public void Add(int x, int y, int z)
    {
        _members.Add(Pack(x, y, z));
    }

    public bool Contains(int x, int y, int z)
    {
        return _members.Contains(Pack(x, y, z));
    }

    private static int Pack(int x, int y, int z)
    {
        if (x < 0 || x > 50)
            throw new ArgumentOutOfRangeException(nameof(x));
        if (y < 0 || y > 6)
            throw new ArgumentOutOfRangeException(nameof(y));
        if (z < 0 || z > 6)
            throw new ArgumentOutOfRangeException(nameof(z));

        return x | y << 8 | z << 16;
    }
}