Linq干掉for循环

 在C系列语言中,for循环扮演着重要的角色。很难想象,一百行C代码里面没有一个for循环(我有个朋友,写了个几千行的算法,没有用的for循环,我当时很惊讶),就好比,一百行中文里面,没有一个"的"。可见,for循环是代码的基本构造块。由于for循环,一般是用来,对一串类型相同的对象进行操作的,从侧面可以看出,它经常伴随着"数组"而来的。用比较通俗的话说,"for循环"与"数组"是黄金搭档。 

    在C#里面,引进了foreach循环,它与for循环本质是相同的,由于在foreach循环中,省去了指标i(常常,只用来取第i个项,别无他用),很多人欣然接受了foreach循环,毕竟没有夺走for循环,它还在!
    编程语言一直在进化,先后经历了:...-汇编语言-...-过程式语言-...-面向对象语言-...。总体来说,越来越高级,越来越抽象。当代程序员可以不知道硬件是啥就可以编程;调用一个sort方法就排序了,不知道用的是"冒泡"还是"快速"排序算法(外国人都帮我们弄好了!每当认识到"差距超过20年"这个事实,我都...,好了,不想伤心事了!)。

    在C# 3.0中,引进了Extension Methods,伴随而来的是一个新玩意儿Linq。用实用工具Reflector.exe打开System.Core.dll中的System.Linq命名空间,有个Enumerable静态类,其中有大量的对"数组"操作的扩展方法(你能想到的基本都有,不信就去看看!)。

    对于用惯了for循环的朋友,如果要他/她停止使用,肯定会觉得日子没法过了。放心好了,我不会劝他/她停止使用的,就像戒烟一样,都是自己的事。(又一次跑题,言归正传!

 

下面我用代码来演示,如何用"扩展方法/Linq"来干掉"for循环":

 

[Test]
public void OldSum()
{
int sum0 = 0;
for (int i = 0; i < 10; i++)
{
sum0 += i;
}
Assert.AreEqual(45, sum0);
}

[Test]
public void NewSum()
{
int sum1 = Enumerable.Range(0, 10).Sum();
int sum2 = Enumerable.Range(0, 10).Aggregate((x, y) => x + y);
int sum3 = Enumerable.Range(0, 10).Aggregate(0, (x, y) => x + y);

Assert.AreEqual(45, sum1);
Assert.AreEqual(45, sum2);
Assert.AreEqual(45, sum3);
}

 

注:无论是对一串数字求和还是求积,归根到底,都是把一串东西变成一个东西,此时就用Aggregate

 

 

 

[Test]
public void OldFilter()
{
int[] arr = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
List<int> odd_list = new List<int>();
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] % 2 == 1)
{
odd_list.Add(arr[i]);
}
}
int[] odd_arr = odd_list.ToArray();
Assert.That(odd_arr, Is.EquivalentTo(new int[] { 1, 3, 5, 7, 9 }));
}

[Test]
public void NewFilter()
{
int[] arr = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int[] odd_arr = arr.Where(x => x % 2 == 1).ToArray();
Assert.That(odd_arr, Is.EquivalentTo(new int[] { 1, 3, 5, 7, 9 }));
}

 

注:无论是取奇数还是偶数,归根到底,都是取一串东西中的某些东西,此时就用Where

 

 

[Test]
public void OldMap()
{
int[] arr = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
List<int> new_list = new List<int>();
for (int i = 0; i < arr.Length; i++)
{
new_list.Add(arr[i] * 10);
}
int[] new_arr = new_list.ToArray();
Assert.That(new_arr, Is.EquivalentTo(new int[] { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 }));
}

[Test]
public void NewMap()
{
int[] arr = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int[] new_arr = arr.Select(x => x * 10).ToArray();
Assert.That(new_arr, Is.EquivalentTo(new int[] { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 }));
}

 

注:无论是x10还是+99,归根到底,都是把一串东西变成一串新东西,此时就用Select

 

 

[Test]
public void PrintMultiplicationFact()
{

Console.Write(
" 1 x 1= 1 \n"
+ " 1 x 2= 2 2 x 2= 4 \n"
+ " 1 x 3= 3 2 x 3= 6 3 x 3= 9 \n"
+ " 1 x 4= 4 2 x 4= 8 3 x 4=12 4 x 4=16 \n"
+ " 1 x 5= 5 2 x 5=10 3 x 5=15 4 x 5=20 5 x 5=25 \n"
+ " 1 x 6= 6 2 x 6=12 3 x 6=18 4 x 6=24 5 x 6=30 6 x 6=36 \n"
+ " 1 x 7= 7 2 x 7=14 3 x 7=21 4 x 7=28 5 x 7=35 6 x 7=42 7 x 7=49 \n"
+ " 1 x 8= 8 2 x 8=16 3 x 8=24 4 x 8=32 5 x 8=40 6 x 8=48 7 x 8=56 8 x 8=64 \n"
+ " 1 x 9= 9 2 x 9=18 3 x 9=27 4 x 9=36 5 x 9=45 6 x 9=54 7 x 9=63 8 x 9=72 9 x 9=81 \n"
);

/*********************方法一: 嵌套循环*************************/
for (int j = 1; j < 10; j++)
{
for (int i = 1; i < 10; i++)
{
if (i <= j)
{
Console.Write("{0, 2} x{1, 2}={2, 2}\t", i, j, i * j);
}
}
Console.Write("\n");
}

/*********************方法二: 扩展方法*************************/
Enumerable.Range(1, 9)
.SelectMany(j => Enumerable.Range(1, 9), (j, i) => new { i, j })
.Where(x => x.i <= x.j)
.GroupBy(x => x.j)
.Select(g => g.Aggregate("", (a, x) => a + string.Format("{0, 2} x{1, 2}={2, 2}\t", x.i, x.j, x.i * x.j)))
.ToList().ForEach(x => Console.WriteLine(x));

/*********************方法三: Linq表达式************************/
(
from j in Enumerable.Range(1, 9)
from i in Enumerable.Range(1, 9)
where i <= j
group new { i, j } by j into g
select new
{
LineNo = g.Key,
Line = g.Aggregate("", (a, x) => a + string.Format("{0, 2} x{1, 2}={2, 2}\t", x.i, x.j, x.i * x.j))
}

).ToList().ForEach(g => Console.WriteLine(g.Line));
}

 

注:对于嵌套的for循环,就用SelectMany

 

声明:for循环很好,你可以继续用,如果你想用的话。如果你喜欢尝试新东西,我想告诉你:"也许可以试试!"

 

附录1:乘法口诀

 

1 x 1= 1
1 x 2= 2 2 x 2= 4
1 x 3= 3 2 x 3= 6 3 x 3= 9
1 x 4= 4 2 x 4= 8 3 x 4=12 4 x 4=16
1 x 5= 5 2 x 5=10 3 x 5=15 4 x 5=20 5 x 5=25
1 x 6= 6 2 x 6=12 3 x 6=18 4 x 6=24 5 x 6=30 6 x 6=36
1 x 7= 7 2 x 7=14 3 x 7=21 4 x 7=28 5 x 7=35 6 x 7=42 7 x 7=49
1 x 8= 8 2 x 8=16 3 x 8=24 4 x 8=32 5 x 8=40 6 x 8=48 7 x 8=56 8 x 8=64
1 x 9= 9 2 x 9=18 3 x 9=27 4 x 9=36 5 x 9=45 6 x 9=54 7 x 9=63 8 x 9=72 9 x 9=81

附录2:完整代码

  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;

namespace KSharp
{
    [TestFixture]
    public class TestForLoop
    {
        [Test]
        public void OldSum()
        {
            int sum0 = 0;
            for (int i = 0; i < 10; i++)
            {
                sum0 += i;
            }
            Assert.AreEqual(45, sum0);
        }

        [Test]
        public void NewSum()
        {
            int sum1 = Enumerable.Range(0, 10).Sum();
            int sum2 = Enumerable.Range(0, 10).Aggregate((x, y) => x + y);
            int sum3 = Enumerable.Range(0, 10).Aggregate(0, (x, y) => x + y);

            Assert.AreEqual(45, sum1);
            Assert.AreEqual(45, sum2);
            Assert.AreEqual(45, sum3);
        }

        [Test]
        public void OldFilter()
        {
            int[] arr = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            List<int> odd_list = new List<int>();
            for (int i = 0; i < arr.Length; i++)
            {
                if (arr[i] % 2 == 1)
                {
                    odd_list.Add(arr[i]);
                }
            }
            int[] odd_arr = odd_list.ToArray();
            Assert.That(odd_arr, Is.EquivalentTo(new int[] { 1, 3, 5, 7, 9 }));
        }

        [Test]
        public void NewFilter()
        {
            int[] arr = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            int[] odd_arr = arr.Where(x => x % 2 == 1).ToArray();
            Assert.That(odd_arr, Is.EquivalentTo(new int[] { 1, 3, 5, 7, 9 }));
        }

        [Test]
        public void OldMap()
        {
            int[] arr = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            List<int> new_list = new List<int>();
            for (int i = 0; i < arr.Length; i++)
            {
                new_list.Add(arr[i] * 10);
            }
            int[] new_arr = new_list.ToArray();
            Assert.That(new_arr, Is.EquivalentTo(new int[] { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 }));
        }

        [Test]
        public void NewMap()
        {
            int[] arr = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            int[] new_arr = arr.Select(x => x * 10).ToArray();
            Assert.That(new_arr, Is.EquivalentTo(new int[] { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 }));
        }


        [Test]
        public void PrintMultiplicationFact()
        {

            Console.Write(
                   " 1 x 1= 1    \n"
                 + " 1 x 2= 2     2 x 2= 4    \n"
                 + " 1 x 3= 3     2 x 3= 6     3 x 3= 9    \n"
                 + " 1 x 4= 4     2 x 4= 8     3 x 4=12     4 x 4=16    \n"
                 + " 1 x 5= 5     2 x 5=10     3 x 5=15     4 x 5=20     5 x 5=25    \n"
                 + " 1 x 6= 6     2 x 6=12     3 x 6=18     4 x 6=24     5 x 6=30     6 x 6=36    \n"
                 + " 1 x 7= 7     2 x 7=14     3 x 7=21     4 x 7=28     5 x 7=35     6 x 7=42     7 x 7=49    \n"
                 + " 1 x 8= 8     2 x 8=16     3 x 8=24     4 x 8=32     5 x 8=40     6 x 8=48     7 x 8=56     8 x 8=64    \n"
                 + " 1 x 9= 9     2 x 9=18     3 x 9=27     4 x 9=36     5 x 9=45     6 x 9=54     7 x 9=63     8 x 9=72     9 x 9=81    \n"
            );

            /*********************方法一: 嵌套循环*************************/
            for (int j = 1; j < 10; j++)
            {
                for (int i = 1; i < 10; i++)
                {
                    if (i <= j)
                    {
                        Console.Write("{0, 2} x{1, 2}={2, 2}\t", i, j, i * j);
                    }
                }
                Console.Write("\n");
            }

            /*********************方法二: 扩展方法*************************/
            Enumerable.Range(1, 9)
                    .SelectMany(j => Enumerable.Range(1, 9), (j, i) => new { i, j })
                    .Where(x => x.i <= x.j)
                    .GroupBy(x => x.j)
                    .Select(g => g.Aggregate("", (a, x) => a + string.Format("{0, 2} x{1, 2}={2, 2}\t", x.i, x.j, x.i * x.j)))
                    .ToList().ForEach(x => Console.WriteLine(x));

            /*********************方法三: Linq表达式************************/
            (
                from j in Enumerable.Range(1, 9)
                from i in Enumerable.Range(1, 9)
                where i <= j
                group new { i, j } by j into g
                select new
                {
                    LineNo = g.Key,
                    Line = g.Aggregate("", (a, x) => a + string.Format("{0, 2} x{1, 2}={2, 2}\t", x.i, x.j, x.i * x.j))
                }

            ).ToList().ForEach(g => Console.WriteLine(g.Line));
        }
    }

  

转载于:https://www.cnblogs.com/jizhongfong/p/4498456.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值