Unity的C#编程教程_62_语言集成查询 LINQ 详解及应用练习

2023-11-17

LINQ: Querys

1. Any

  • LINQ: Language Integrated Query 语言集成查询

  • 类似 MySQL,允许过滤数据(array 和 list)

  • 任务说明:

    • 建立一个名字的数组
    • 查询某个名字是否在该数组中

之前的做法:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LinqTest : MonoBehaviour
{
    public string[] names = { "xiaoA", "xiaoB", "xiaoC", "xiaoD" };

    // Start is called before the first frame update
    void Start()
    {
        foreach(var name in names)
        {
            if(name == "xiaoC")
            {
                Debug.Log("Name found!");
            }
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

改用 LINQ:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq; // LINQ 需要使用这个库

public class LinqTest : MonoBehaviour
{
    public string[] names = { "xiaoA", "xiaoB", "xiaoC", "xiaoD" };

    // Start is called before the first frame update
    void Start()
    {
        /*
        foreach(var name in names)
        {
            if(name == "xiaoC")
            {
                Debug.Log("Name found!");
            }
        }
        */

        var answer = names.Any(name => name == "xiaoE");
        // 在 names 数组中,是否有任何满足条件的元素?
        // 条件是 name == "xiaoC"
        // 返回的是 bool 值
        Debug.Log("Fond xiaoE? Answer: " + answer);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

2. Contains

  • 用于判断是否存在具体的元素
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq; // LINQ 需要使用这个库

public class LinqTest : MonoBehaviour
{
    public string[] names = { "xiaoA", "xiaoB", "xiaoC", "xiaoD" };

    // Start is called before the first frame update
    void Start()
    {
        /*
        foreach(var name in names)
        {
            if(name == "xiaoC")
            {
                Debug.Log("Name found!");
            }
        }
        */

        /*
        var answer = names.Any(name => name == "xiaoE");
        // 在 names 数组中,是否有任何元素可以满足特定条件?
        // 条件是 name == "xiaoC"
        // 返回的是 bool 值
        */

        var answer = names.Contains("xiaoE");

        Debug.Log("Fond xiaoE? Answer: " + answer);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

3. Distinct

  • 去除重复元素
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq; // LINQ 需要使用这个库

public class LinqTest : MonoBehaviour
{
    public string[] names = new string[] { "xiaoA", "xiaoA", "xiaoB", "xiaoC", "xiaoD" };

    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Before");
        foreach (string name in names)
        {
            Debug.Log(name);
        }


        var newNames = names.Distinct();
        // Distinct 不会直接作用于原数组,所以需要赋值到一个新的变量

        Debug.Log("New");
        foreach (var name in newNames)
        {
            Debug.Log(name);
        }

        Debug.Log("After");
        foreach (var name in names)
        {
            Debug.Log(name);
        }
        
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

注意,Distinct 不会直接修改原数组。

4. Where

  • 为序列按照指定条件筛选
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq; // LINQ 需要使用这个库

public class LinqTest : MonoBehaviour
{
    public string[] names = new string[] { "xiaoAA", "xiaoA", "xiaoBB", "xiaoCCCC", "xiaoDDDD" };

    // Start is called before the first frame update
    void Start()
    {
        var newNames = names.Where(name => name.Length > 6);
        // 对于原来数组中的元素进行筛选
        // 筛选条件是:长度大于 6

        foreach(var name in newNames)
        {
            Debug.Log(name);
        }
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

Challenge: Hands on with LINQ

  • 任务说明:
    • 建立一个数组,包含的都是整型元素,每个元素取值范围 0~100
    • 筛选出 50 以上的数据
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq; // LINQ 需要使用这个库

public class LinqTest : MonoBehaviour
{
    public int[] nums = { 10, 20, 35, 66, 78, 98, 45, 23, 67 };

    // Start is called before the first frame update
    void Start()
    {
        var newNums = nums.Where(num => num > 50);

        foreach(var num in newNums)
        {
            Debug.Log(num);
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

LINQ: Order by Descending

  • 筛选后进行排序
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq; // LINQ 需要使用这个库

public class LinqTest : MonoBehaviour
{
    public int[] nums = { 10, 20, 35, 66, 78, 98, 45, 23, 67 };

    // Start is called before the first frame update
    void Start()
    {
        var newNums = nums.Where(num => num > 50).OrderByDescending(n => n);
        // 筛选出大于 50 的元素,然后直接按照降序排列
        // 排序条件可以定制,比如设定 n => -n,其实就按照升序排列了

        foreach (var num in newNums)
        {
            Debug.Log(num);
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

Challenge: Filter Items with LINQ

  • 任务说明:
    • 创建一个 class,用作筛选
    • 筛选对象为游戏道具
    • 查询 id 为 3 的物品是否存在,打印查询结果
    • 筛选 50 元以上的物品,打印查询结果
    • 计算所有道具的平均价格

创建基本脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq; // LINQ 需要使用这个库

[System.Serializable] // 在 inspector 中可见
public class Item
{
    public string name;
    public int id;
    public int price;
}

public class LinqTest : MonoBehaviour
{
    public List<Item> items;

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

然后在 inspector 中创建一些 item。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq; // LINQ 需要使用这个库

[System.Serializable] // 在 inspector 中可见
public class Item
{
    public string name;
    public int id;
    public int price;
}

public class LinqTest : MonoBehaviour
{
    public List<Item> items;

    // Start is called before the first frame update
    void Start()
    {
        var result = items.Any(item => item.id == 3);
        Debug.Log("Fond id of 3: " + result);

        var newItems = items.Where(item => item.price > 50);
        foreach(var item in newItems)
        {
            Debug.Log("Item: " + item.name + " Price: " + item.price);
        }

        var total = items.Sum(item => item.price); // 求总价
        float averagePrice = (float)total / items.Count(); // 平均价
        // 为了确保平均价格为浮点数,这里把 total 设置为 float
        Debug.Log("Average price: " + averagePrice);

        // 也可以直接使用 average:
        var average = items.Average(item => item.price);
        Debug.Log("Average price: " + average);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

LINQ: How to Read and Convert Query Syntax

  • LINQ 的另一种使用方法:查询语法(query syntax)

微软官方示例:

class LINQQueryExpressions
{
    static void Main()
    {

        // Specify the data source.
        int[] scores = new int[] { 97, 92, 81, 60 };

        // Define the query expression.
        IEnumerable<int> scoreQuery =
            from score in scores
            where score > 80
            select score; // select 语句是必须的

        // Execute the query.
        foreach (int i in scoreQuery)
        {
            Console.Write(i + " ");
        }
    }
}
// Output: 97 92 81

放到 unity 的脚本中:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq; // LINQ 需要使用这个库

public class LinqTest : MonoBehaviour
{
    // Specify the data source.
    int[] scores = new int[] { 97, 92, 81, 60 };

    // Start is called before the first frame update
    void Start()
    {
        // Define the query expression.
        IEnumerable<int> scoreQuery =
            from score in scores
            where score > 80
            select score;

        // Execute the query.
        foreach (int i in scoreQuery)
        {
            Debug.Log(i + " ");
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

这里使用的就是查询语法(query syntax),如何转化为 method syntax 呢:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq; // LINQ 需要使用这个库

public class LinqTest : MonoBehaviour
{
    // Specify the data source.
    int[] scores = new int[] { 97, 92, 81, 60 };

    // Start is called before the first frame update
    void Start()
    {
        // Define the query expression.
        /*
        IEnumerable<int> scoreQuery =
            from score in scores
            where score > 80
            select score;
        */
        var scoreQuery = scores.Where(score => score > 80);

        // Execute the query.
        foreach (int i in scoreQuery)
        {
            Debug.Log(i + " ");
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

推荐使用 method syntax,更简洁易用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Unity的C#编程教程_62_语言集成查询 LINQ 详解及应用练习 的相关文章

  • 为什么使用abs()或fabs()而不是条件否定?

    在 C C 中 为什么要使用abs or fabs 不使用以下代码即可查找变量的绝对值 int absoluteValue value lt 0 value value 这与较低级别的指令较少有关吗 您提出的 有条件的abs 并不等于std
  • 如何在 VS 中键入时显示方法的完整文档?

    标题非常具有描述性 是否有任何扩展可以让我看到我正在输入的方法的完整文档 我想查看文档 因为我可以在对象浏览器中看到它 其中包含参数的描述和所有内容 而不仅仅是一些 摘要 当然可以选择查看所有覆盖 它可能是智能感知的一部分 或者我不知道它并
  • 转到 C# WPF 中的第一页

    我正在 WPF 中使用导航服务 为了导航到页面 我使用 this NavigationService Navigate new MyPage 为了返回我使用 this NavigationService GoBack 但是如何在不使用的情况
  • C++派生模板类继承自模板基类,无法调用基类构造函数[重复]

    这个问题在这里已经有答案了 我试图从基类 模板 继承 派生类也是模板 它们具有相同的类型 T 我收到编译错误 非法成员初始化 Base 不是基类或成员 为什么 如何调用基类构造函数 include
  • 用于从字符串安全转换的辅助函数

    回到 VB6 我编写了一些函数 让我在编码时无需关心字符串的 null 和 数字的 null 和 0 等之间的区别 编码时 没有什么比添加特殊情况更能降低我的工作效率了用于处理可能导致一些不相关错误的数据的代码 9999 10000 如果我
  • “MyClass”的类型初始值设定项引发异常

    以下是我的Windows服务代码 当我调试代码时 我收到错误 异常 CSMessageUtility CSDetails 的类型初始值设定项引发异常 using System using System Collections Generic
  • C# using 语句、SQL 和 SqlConnection

    使用 using 语句 C SQL 可以吗 private static void CreateCommand string queryString string connectionString using SqlConnection c
  • 如何排列表格中的项目 - MVC3 视图 (Index.cshtml)

    我想使用 ASP NET MVC3 显示特定类型食品样本中存在的不同类型维生素的含量 如何在我的视图 Index cshtml 中显示它 an example 这些是我的代码 table tr th th foreach var m in
  • 在 C 中复制两个相邻字节的最快方法是什么?

    好吧 让我们从最明显的解决方案开始 memcpy Ptr const char a b 2 调用库函数的开销相当大 编译器有时不会优化它 我不会依赖编译器优化 但即使 GCC 很聪明 如果我将程序移植到带有垃圾编译器的更奇特的平台上 我也不
  • 通过等待任务或访问其 Exception 属性都没有观察到任务的异常

    这些是我的任务 我应该如何修改它们以防止出现此错误 我检查了其他类似的线程 但我正在使用等待并继续 那么这个错误是怎么发生的呢 通过等待任务或访问其 Exception 属性都没有观察到任务的异常 结果 未观察到的异常被终结器线程重新抛出
  • 过期时自动重新填充缓存

    我当前缓存方法调用的结果 缓存代码遵循标准模式 如果存在 则使用缓存中的项目 否则计算结果 在返回之前将其缓存以供将来调用 我想保护客户端代码免受缓存未命中的影响 例如 当项目过期时 我正在考虑生成一个线程来等待缓存对象的生命周期 然后运行
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 无法使用 Ninject 将依赖项注入到从 Angular 服务调用的 ASP.NET Web API 控制器中

    我将 Ninject 与 ASP NET MVC 4 一起使用 我正在使用存储库 并希望进行构造函数注入以将存储库传递给其中一个控制器 这是实现 StatTracker 接口的上下文对象 EntityFramework public cla
  • 内核开发和 C++ [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 从我know https stackoverflow com questions 580292 what languages are windo
  • Fluent NHibernate 日期时间 UTC

    我想创建一个流畅的 nhibernate 映射来通过以下方式映射 DateTime 字段 保存时 保存 UTC 值 读取时 调整为本地时区值 实现此映射的最佳方法是什么 就我个人而言 我会将日期存储在 UTC 格式的对象中 然后在读 写时在
  • 我应该在应用程序退出之前运行 Dispose 吗?

    我应该在应用程序退出之前运行 Dispose 吗 例如 我创建了许多对象 其中一些对象具有事件订阅 var myObject new MyClass myObject OnEvent OnEventHandle 例如 在我的工作中 我应该使
  • 为什么 Ajax.BeginForm 在 Chrome 中不起作用?

    我正在使用 c NET MVC2 并尝试创建一个 ajax 表单来调用删除数据库记录 RemoveRelation 的方法 删除记录的过程正在按预期进行 删除记录后 表单应调用一个 JavaScript 函数 从视觉效果中删除该记录 Rem
  • 以编程方式使用自定义元素创建网格

    我正在尝试以编程方式创建一个网格 并将自定义控件作为子项附加到网格中 作为 2x2 矩阵中的第 0 行第 0 列 为了让事情变得更棘手 我使用了 MVVM 设计模式 下面是一些代码可以帮助大家理解这个想法 应用程序 xaml cs base
  • 热重载时调用方法

    我正在使用 Visual Studio 2022 和 C 制作游戏 我想知道当您热重新加载应用程序 当它正在运行时 时是否可以触发一些代码 我基本上有 2 个名为 UnloadLevel 和 LoadLevel 的方法 我想在热重载时执行它
  • Swagger 为 ASP.CORE 3 中的字典生成错误的 URL

    当从查询字符串中提取的模型将字典作为其属性之一时 Swagger 会生成不正确的 URL 如何告诉 Swagger 更改 URL 中字典的格式或手动定义输入参数模式而不自动生成 尝试使用 Swashbuckle 和 NSwag 控制器 pu

随机推荐