实现循环的三重境界

缘起

王国维歪解宋词,用它表达事业的三重境界。老谭要谈谈C#中编写循环的三种方式,也来个东施效颦,不过是用唐诗来表达。王国维选择宋词,非常贴切,也给宋词增色不少。老谭没这水平,只是乱选一气。

我们的例子是报表查询:根据给定的关键字,查询符合条件的报表,即报表名字是否和关键字相匹配。关键字的结构类似于Google查询:关键字中包含多个单词,单词由空格或加号隔开,空格表示或者,加号表示而且。

例如,如果关键字是 二厂 三厂,那么名字中含有二厂或三厂的报表都能匹配上,如果关键字是化工+预测,那么名字中既含有化工,又含有预测的报表,才能匹配上。

我们要实现的函数是 bool IsMatched(string reportName, string keyword)。

方式1:我舞影零乱

我们可以采用最为传统的for循环实现这个函数:

private bool IsMatched(string reportName, string keyword)
{
    string[] orItems = keyword.Split(' ');
    int orItemCount = orItems.Length;
    for (int i = 0; i < orItemCount; i ++)
    {
        string[] andItems = orItems[i].Split('+');

        bool allMatched = true;

        int andItemCount = andItems.Length;

        for (int j = 0; allMatched && j < andItemCount; j++)
        {
            if (!reportName.Contains(andItem[j]))
            {
                allMatched = false;
                break;
            }
        }

        if (allMatched)
        {
            return true;
        }
    }

    return false;
}

在这种方式下,为了实现循环,需要做相当多的额外工作:

  1. 定义循环控制变量,如i、j;
  2. 初始化循环控制变量,如设置为0;
  3. 定义循环控制变量的结束条件,如不超过项目个数;
  4. 每一个循环步骤中调整循环控制变量的值,如加1;
  5. 根据循环控制变量获取到要操作的对象等。

这些“额外”工作,遮蔽了要实现的逻辑,非常容易导致错误,如循环控制变量用混。

方式2:竹露滴清响

为了解决方式1中的诸多问题,C#添加了foreach关键字,支持新的循环实现方式。

private bool IsMatched(string reportName, string keyword)
{
    foreach (string orItem in keyword.Split(' '))
    {
        bool allMatched = true;

        foreach (var andItem in orItem.Split('+'))
        {
            if (!reportName.Contains(andItem))
            {
                allMatched = false;
                break;
            }
        }

        if (allMatched)
        {
            return true;
        }
    }

    return false;
}

这种方式克服了方式1的缺点,循环控制不再凌乱,程序逻辑集中于处理循环变量上。这些变量,从集合中一个个涌出,像滴着清响的竹露般利索。

方式3:循环不可寻

C#采纳了函数式编程的思路,和我们熟悉的命令式编程方式混合在一起,变成了一种混合式编程语言。

private bool IsMatched(string reportName, string keyword)
{
    return keyword.Split(' ').Any(orItem => orItem.Split('+').All(reportName.Contains));
}

这时,循环杳无踪影。

转换思路

利用C#操作集合时,要做好思路的转换:从命令式(imperative)到函数式(functional)的转换。这是一个大题目,这里只提本例子中用到的两点:

  1. 明确做什么,而不是怎么做。如检查集合中全部元素符合某个条件,用All(),检查集合中是否有一个元素符合某个条件,用Any()。具体怎么做,或者利用开发平台提供的支持,或者自己实现;
  2. 将函数作为参数。如Any、All都是函数,同时也是参数。显然,C#中是用λ-表达式做到这一点的。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值