LinQ 查询表达式大全 Unity UniRx 中文目录-Chinar

37 篇文章 5 订阅

Chinar blog www.chinar.xin


UnitRx LinQ 表达式全解



本文提供全流程,中文翻译。

Chinar 坚持将简单的生活方式,带给世人!

(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例)

Chinar —— 心分享、心创新!

助力查询学习 LinQ 查询语句的具体用法、可用于备忘

为新手节省宝贵的时间,避免采坑!

Chinar 教程效果:暂时留空



全文高清图片,点击即可放大观看 (很多人竟然不知道)


1. Where —— 筛选条件


Where —— 使满足条件的数据通过,排除被限制的元素

举个例子

查询狗狗数据中,重量大于 30 的狗

// ========================================================
// 描述:Where 筛选满足/限制条件
// 作者:Chinar 
// 创建时间:2019-01-03 23:55:27
// 版 本:1.0
// ========================================================
using System.Collections.Generic;
using System.Linq;
using UnityEngine;


namespace ChinarDemo.LinQ
{
    public class Chinar_Where : MonoBehaviour
    {
        void Start()
        {
            //一个数据列表,并添加数据
            List<Dog> dogs = new List<Dog>()
            {
                new Dog("金毛",  2000, 62),
                new Dog("二哈",  1500, 45),
                new Dog("泰迪",  1000, 15),
                new Dog("吉娃娃", 500,  10)
            };
            //1-查询 狗狗中 重量大于30
            dogs.Where(dog => dog.Weight > 30).ToList().ForEach(dog => print(dog.ToString()));
            //2-LinQ 查询 狗狗中 重量大于30
            (from dog in dogs where dog.Weight > 30 select dog).ToList().ForEach(dog => print(dog.ToString()));
        }
    }
}

打印输出:

Name: 金毛, Price: 2000, Weight: 62
Name: 二哈, Price: 1500, Weight: 45

Name: 金毛, Price: 2000, Weight: 62
Name: 二哈, Price: 1500, Weight: 45

数据类 —— 为了简化代码,将该类放于 ChinarDemo.LinQ 命名空间中。便于以下例子使用此数据!

namespace ChinarDemo.LinQ
{
    /// <summary>
    /// 狗狗数据类
    /// </summary>
    public class Dog
    {
        public string Name;   //名称
        public int    Price;  //价格
        public float  Weight; //重量


        /// <summary>
        /// 构造 —— 简化代码
        /// </summary>
        public Dog(string name, int price, float weight)
        {
            Name   = name;
            Price  = price;
            Weight = weight;
        }


        /// <summary>
        /// 便于打印输出看效果 —— 简化代码
        /// </summary>
        public override string ToString()
        {
            return $"{nameof(Name)}: {Name}, {nameof(Price)}: {Price}, {nameof(Weight)}: {Weight}";
        }
    }
}

2. Select —— 返回选定类型


Select —— 选择并返回相应数据类型

举个例子

每帧,监听左键点击与右键点击,并选择需要返回的数据类型,打印输出!

using UniRx;
using UniRx.Triggers;
using UnityEngine;


namespace ChinarDemo.LinQ
{
    public class LinQ_Select : MonoBehaviour
    {
        int count = 0;


        /// <summary>
        /// 1 —— UniRx表达式
        /// 点右键
        /// </summary>
        void Start()
        {
            this.UpdateAsObservable()
                .Where(_ => Input.GetMouseButtonDown(1)) //条件
                .Select(_ => "Chinar右" + count++)         //返回 字符串 —— Chinar0 / Chinar1 / Chinar...
                .Subscribe(print);                       // print 等同于<  .Subscribe(chinarEvent=>print(chinarEvent))  >
                
            LinQ();
        }


        /// <summary>
        /// 2 —— 查询表达式
        /// 点左键
        /// </summary>
        private void LinQ()
        {
            (from _ in this.UpdateAsObservable() where Input.GetMouseButtonDown(0) select "Chinar左" + count++).Subscribe(print);
        }
    }
}

打印输出:
在这里插入图片描述


2.1 SelectMany —— 返回多个选定类型/协程排序


SelectMany —— 选择并返回相应数据类型,是在Select的基础上,返回了多个类型
在 UniRx 中多用于对协程执行顺序进行管理

举个例子

下面例子中,将狗狗的名字拆分为字符类型,并返回
对3个协程依照需求顺序执行

public class Chinar_SelectMany : MonoBehaviour
{
    private List<Dog> dogs;


    /// <summary>
    /// 初始化函数
    /// </summary>
    void Start()
    {
        dogs = new List<Dog>() //该数据用的是 1 中写好的数据
        {
            new Dog("金毛",  2000, 62),
            new Dog("二哈",  1500, 45),
            new Dog("泰迪",  1000, 15),
            new Dog("吉娃娃", 500,  10)
        };
        dogs.ToObservable().SelectMany(_ => _.Name).Subscribe(_ => print(_)); //从列表中选择返回名字,并切分为Char类型
        Chinar_UniRx();
    }


    private void LinQ()
    {
        dogs.SelectMany(_ => _.Name).ToList().ForEach(_ => print(_));
    }


    /// <summary>
    /// 在 UniRx 中的用法,可将协程以需要的顺序执行
    /// </summary>
    private void Chinar_UniRx()
    {
        var ie1 = Observable.FromCoroutine(Ie1);
        var ie2 = Observable.FromCoroutine(Ie2);
        var ie3 = Observable.FromCoroutine(Ie3);
        ie3.SelectMany(ie2.SelectMany(ie1)).Subscribe(); //协程执行顺序一一对应: 3-2-1
    }


    IEnumerator Ie1()
    {
        yield return new WaitForSeconds(0.5f);
        print(1);
    }


    IEnumerator Ie2()
    {
        yield return new WaitForSeconds(0.5f);
        print(2);
    }


    IEnumerator Ie3()
    {
        yield return new WaitForSeconds(0.5f);
        print(3);
    }
}

打印输出:
在这里插入图片描述


3. First —— 首次/第一个数据


First —— 数据 / 事件中,满足条件的第一个

举个例子

1-无论点击多少次,只会只在首次点击左键时输出 0
2-只取第一个,数组中满足条件的元素

using System.Linq;
using UniRx;
using UniRx.Triggers;
using UnityEngine;


namespace ChinarDemo.LinQ
{
    public class Chinar_First : MonoBehaviour
    {
        private int count = 0;


        void Start()
        {
            this.UpdateAsObservable()
                .First(_ => Input.GetMouseButtonDown(0)) //第一次点击左键时
                .Subscribe(_ => print(count++));         // 无论点击多少次,只会只在首次点击左键时输出 0
            LinQ();
        }


        private void LinQ()
        {
            int[] numbers  = {1, 2, 3, 4, 5, 6};        //数组
            var   numFirst = numbers.First(i => i > 3); //返回满足条件的第一个数据元素
            print(numFirst);                            //输出 4
        }
    }
}

打印输出:
在这里插入图片描述


4. Distinct —— 找不同


Distinct —— 数据/事件中的不同元素通过,相同元素被剔除


如:1122334 经过剔除,会变成 1234

举个例子

剔除Update事件流中相同的事件

找到数字列表中不同的数字

public class Chinar_Distinct : MonoBehaviour
{
    /// <summary>
    /// 初始化函数
    /// </summary>
    void Start()
    {
        int count = 0;
        //只输出一次0,因为之后的事件流,都重复了(这里剔除的是相同的事件流,而不是数字)
        this.UpdateAsObservable().Distinct().Subscribe(_ => print("在 Update 事件中" + ++count + " 次数"));
        LinQ();
    }


    private void LinQ()
    {
        //一个数据列表,并添加数据
        List<int> ints = new List<int>()
        {
            1, 2, 3, 2, 3, 4, 5, 6, 7, 8, 9, 10
        };
        ints.Distinct().ToList().ForEach(_ => print(_)); //遍历输出,剔除后的列表
    }
}

打印输出:
在这里插入图片描述


5. Last —— 找不同


Last —— 最后一个元素

举个例子

找到狗狗中的最后一个/满足条件狗狗中的最后一个

using System.Collections.Generic;
using System.Linq;
using ChinarX.LinQ;
using UniRx;
using UnityEngine;


public class Chinar_Last : MonoBehaviour
{
    void Start()
    {
        List<Dog> dogs = new List<Dog>()//该数据用的是 1 中写好的数据
        {
            new Dog("金毛",  2000, 62),
            new Dog("二哈",  1500, 45),
            new Dog("泰迪",  1000, 15),
            new Dog("吉娃娃", 500,  10)
        };
        Dog dog = dogs.Last();                     //最后一个
        print(dog.ToString());                     //:吉娃娃
        Dog dog1 = dogs.Last(_ => _.Price > 1000); //传入条件:价格在 1000以上 的狗中的最后一个
        print(dog1.ToString());                    //:二哈
    }
}

打印输出:

Name: 吉娃娃, Price: 500, Weight: 10

Name: 二哈, Price: 1500, Weight: 45

6. Last —— 找不同


Last —— 最后一个元素

举个例子

找到狗狗中的最后一个/满足条件狗狗中的最后一个

using System.Collections.Generic;
using System.Linq;
using ChinarX.LinQ;
using UniRx;
using UnityEngine;


public class Chinar_Last : MonoBehaviour
{
    void Start()
    {
        List<Dog> dogs = new List<Dog>()//该数据用的是 1 中写好的数据
        {
            new Dog("金毛",  2000, 62),
            new Dog("二哈",  1500, 45),
            new Dog("泰迪",  1000, 15),
            new Dog("吉娃娃", 500,  10)
        };
        Dog dog = dogs.Last();                     //最后一个
        print(dog.ToString());                     //:吉娃娃
        Dog dog1 = dogs.Last(_ => _.Price > 1000); //传入条件:价格在 1000以上 的狗中的最后一个
        print(dog1.ToString());                    //:二哈
    }
}

打印输出:

Name: 吉娃娃, Price: 500, Weight: 10

Name: 二哈, Price: 1500, Weight: 45

5

Coroutine —— 协程


Observable.FromCoroutine(协程函数) —— 协程转 Observable

Observable.Timer(TimeSpan.FromSeconds(1)).ToYieldInstruction() —— Observable 转 Yield
举个例子

    void Start()
    {
        Observable.FromCoroutine(TestIEnumerator); //协程转 Observable
    }


    private IEnumerator TestIEnumerator()
    {
        yield return Observable.Timer(TimeSpan.FromSeconds(1)).ToYieldInstruction(); // 转 指令、
        print("Chinar Test-Func");
    }

6

WhenAll —— 等待执行完毕


Where() —— 当多个事件流,需要根据逻辑满足所有都执行后,才触发执行
举个例子

1:等待2个协程执行完毕
2:当所有事件执行完毕后

    void Start()
    {
        //第一种:等待协程都执行完毕
        var streamA = Observable.FromCoroutine(A);
        var streamB = Observable.FromCoroutine(B);
        Observable.WhenAll(streamA, streamB).Subscribe(_ => print("WenAll执行成功!"));

        //第二种:所有操作执行一次后,执行以下订阅
        var event1 = this.UpdateAsObservable().Where(_ => Input.GetMouseButtonDown(0)).First();
        var event2 = this.UpdateAsObservable().Where(_ => Input.GetMouseButtonDown(1)).First();
        Observable.WhenAll(event1, event2).Subscribe(_ => print("左右键执行一次后,执行操作!"));
    }


    IEnumerator A()
    {
        yield return new WaitForSeconds(1);
        print("A");
    }


    IEnumerator B()
    {
        yield return new WaitForSeconds(2);
        print("B");
    }

7

Thread —— 线程


Observable.Start() —— 开启一个线程

ObserveOnMainThread() —— 线程结果返回到主线程中,在主线程中观察
举个例子

    void Start()
    {
        var stream1 = Observable.Start(() =>
        {
            Thread.Sleep(5000);//5000毫秒
            print("等待了5秒");
            return 1;
        }); //线程1
        var stream2 = Observable.Start(() =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            print("等待2秒");
            return 2;
        }); //线程2

        
        Observable.WhenAll(stream1, stream2).ObserveOnMainThread().Subscribe(_ => //当线程执行完毕,将其他线程中的值,返回到主线程中
        {
            print(_[0]);
            print(_[1]);
        });
    }

执行顺序
在这里插入图片描述


8

ObservableWWW —— RX-WWW请求


new ScheduledNotifier<float>() —— 声明一个预定进度对象

ObserveOnMainThread() —— 线程结果返回到主线程中,在主线程中观察
举个例子

        //第一个 print,请求正常信息
        //第二个 print,错误信息
        ObservableWWW.Get("http://www.chinar.xin/asdf").Subscribe(print, print);//请求一个错误的网路地址
    void Start()
    {
        var slider           = GameObject.Find("Slider").GetComponent<Slider>();                                                                    //滑动器
        var progressText     = GameObject.Find("ProgressText").GetComponent<Text>();                                                                //进度条文本
        var progressNotifier = new ScheduledNotifier<float>();                                                                                      //RX 预定通知 float
        ObservableWWW.GetAndGetBytes("http://www.chinar.xin/TestUpdate/granulesprite.unity3d", progress: progressNotifier).Subscribe(bytes => { }); //下载完成,做储存
        progressNotifier.Subscribe(progressFloat => { slider.value = progressFloat; });                                                             //更新进度
        progressNotifier.SubscribeToText(progressText);                                                                                             //进度值显示在 progressText
    }

在这里插入图片描述


7

Thread —— 线程


Observable.Start() —— 开启一个线程

ObserveOnMainThread() —— 线程结果返回到主线程中,在主线程中观察
举个例子

    void Start()
    {
        var stream1 = Observable.Start(() =>
        {
            Thread.Sleep(4000);//4000毫秒
            print("等待了4秒");
            return 1;
        }); //线程1
        var stream2 = Observable.Start(() =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            print("等待2秒");
            return 2;
        }); //线程2

        
        Observable.WhenAll(stream1, stream2).ObserveOnMainThread().Subscribe(_ => //当线程执行完毕,将其他线程中的值,返回到主线程中
        {
            print(_[0]);
            print(_[1]);
        });
    }

执行顺序
在这里插入图片描述


7

Thread —— 线程


Observable.Start() —— 开启一个线程

ObserveOnMainThread() —— 线程结果返回到主线程中,在主线程中观察
举个例子

    void Start()
    {
        var stream1 = Observable.Start(() =>
        {
            Thread.Sleep(4000);//4000毫秒
            print("等待了4秒");
            return 1;
        }); //线程1
        var stream2 = Observable.Start(() =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            print("等待2秒");
            return 2;
        }); //线程2

        
        Observable.WhenAll(stream1, stream2).ObserveOnMainThread().Subscribe(_ => //当线程执行完毕,将其他线程中的值,返回到主线程中
        {
            print(_[0]);
            print(_[1]);
        });
    }

执行顺序
在这里插入图片描述


7

Thread —— 线程


Observable.Start() —— 开启一个线程

ObserveOnMainThread() —— 线程结果返回到主线程中,在主线程中观察
举个例子

    void Start()
    {
        var stream1 = Observable.Start(() =>
        {
            Thread.Sleep(4000);//4000毫秒
            print("等待了4秒");
            return 1;
        }); //线程1
        var stream2 = Observable.Start(() =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            print("等待2秒");
            return 2;
        }); //线程2

        
        Observable.WhenAll(stream1, stream2).ObserveOnMainThread().Subscribe(_ => //当线程执行完毕,将其他线程中的值,返回到主线程中
        {
            print(_[0]);
            print(_[1]);
        });
    }

执行顺序
在这里插入图片描述


7

Thread —— 线程


Observable.Start() —— 开启一个线程

ObserveOnMainThread() —— 线程结果返回到主线程中,在主线程中观察
举个例子

    void Start()
    {
        var stream1 = Observable.Start(() =>
        {
            Thread.Sleep(4000);//4000毫秒
            print("等待了4秒");
            return 1;
        }); //线程1
        var stream2 = Observable.Start(() =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            print("等待2秒");
            return 2;
        }); //线程2

        
        Observable.WhenAll(stream1, stream2).ObserveOnMainThread().Subscribe(_ => //当线程执行完毕,将其他线程中的值,返回到主线程中
        {
            print(_[0]);
            print(_[1]);
        });
    }

执行顺序
在这里插入图片描述


7

Thread —— 线程


Observable.Start() —— 开启一个线程

ObserveOnMainThread() —— 线程结果返回到主线程中,在主线程中观察
举个例子

    void Start()
    {
        var stream1 = Observable.Start(() =>
        {
            Thread.Sleep(4000);//4000毫秒
            print("等待了4秒");
            return 1;
        }); //线程1
        var stream2 = Observable.Start(() =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            print("等待2秒");
            return 2;
        }); //线程2

        
        Observable.WhenAll(stream1, stream2).ObserveOnMainThread().Subscribe(_ => //当线程执行完毕,将其他线程中的值,返回到主线程中
        {
            print(_[0]);
            print(_[1]);
        });
    }

执行顺序
在这里插入图片描述


支持

May Be —— 开发者,总有一天要做的事!


拥有自己的服务器,无需再找攻略

Chinar 提供一站式《零》基础教程

使有限时间 具备无限可能!

Chinar 知你所想,予你所求!( Chinar Blog )


Chinar

END

本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com

对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值