Linq中的投影运算 (C#):Select、SelectMany、Zip

news2025/1/16 4:58:54

投影是指将对象转换为一种新形式的操作,该形式通常只包含那些将随后使用的属性。 通过使用投影,您可以构造从每个对象生成的新类型。 可以投影属性,并对该属性执行数学函数。 还可以在不更改原始对象的情况下投影该对象。

1、Select

下面的示例使用 select 子句来投影字符串列表中每个字符串的第一个字母。两个等效查询

List<string> words = ["an", "apple", "a", "day"];

var query = from word in words
            select word.Substring(0, 1);

foreach (string s in query)
{
    Console.WriteLine(s);
}

/* This code produces the following output:

    a
    a
    a
    d
*/
List<string> words = ["an", "apple", "a", "day"];

var query = words.Select(word => word.Substring(0, 1));

foreach (string s in query)
{
    Console.WriteLine(s);
}

/* This code produces the following output:

    a
    a
    a
    d
*/

2、SelectMany

下面的示例使用多个 from 子句来投影字符串列表中每个字符串中的每个单词。

List<string> phrases = ["an apple a day", "the quick brown fox"];

var query = from phrase in phrases
            from word in phrase.Split(' ')
            select word;

foreach (string s in query)
{
    Console.WriteLine(s);
}

/* This code produces the following output:

    an
    apple
    a
    day
    the
    quick
    brown
    fox
*/

以下代码显示了使用方法语法的等效查询:

List<string> phrases = ["an apple a day", "the quick brown fox"];

var query = phrases.SelectMany(phrases => phrases.Split(' '));

foreach (string s in query)
{
    Console.WriteLine(s);
}

/* This code produces the following output:

    an
    apple
    a
    day
    the
    quick
    brown
    fox
*/

该方法 SelectMany 还可以形成匹配第一个序列中的每个项与第二个序列中的每个项的组合:

var query = from number in numbers
            from letter in letters
            select (number, letter);

foreach (var item in query)
{
    Console.WriteLine(item);
}

以下代码显示了使用方法语法的等效查询:

var method = numbers
    .SelectMany(number => letters,
    (number, letter) => (number, letter));

foreach (var item in method)
{
    Console.WriteLine(item);
}

3、Zip

Zip 投影运算符有多个重载。 所有 Zip 方法都处理两个或更多可能是异构类型的序列。 前两个重载返回元组,具有来自给定序列的相应位置类型。

1)、第一个重载

// An int array with 7 elements.
IEnumerable<int> numbers = [1, 2, 3, 4, 5, 6, 7];
// A char array with 6 elements.
IEnumerable<char> letters = ['A', 'B', 'C', 'D', 'E', 'F'];

若要将这些序列一起投影,请使用 Enumerable.Zip<TFirst,TSecond>(IEnumerable<TFirst>, IEnumerable<TSecond>) 运算符:

foreach ((int number, char letter) in numbers.Zip(letters))
{
    Console.WriteLine($"Number: {number} zipped with letter: '{letter}'");
}
// This code produces the following output:
//     Number: 1 zipped with letter: 'A'
//     Number: 2 zipped with letter: 'B'
//     Number: 3 zipped with letter: 'C'
//     Number: 4 zipped with letter: 'D'
//     Number: 5 zipped with letter: 'E'
//     Number: 6 zipped with letter: 'F'

注:zip 操作生成的序列的长度永远不会长于最短序列。 numbers 和 letters 集合的长度不同,生成的序列将省略 numbers 集合中的最后一个元素,因为它没有任何要压缩的内容。

2)、第二个重载

第二个重载接受 third 序列。 让我们创建另一个集合,即 emoji

// A string array with 8 elements.
IEnumerable<string> emoji = [ "🤓", "🔥", "🎉", "👀", "⭐", "💜", "✔", "💯"];

若要将这些序列一起投影,请使用 Enumerable.Zip<TFirst,TSecond,TThird>(IEnumerable<TFirst>, IEnumerable<TSecond>, IEnumerable<TThird>) 运算符:

foreach ((int number, char letter, string em) in numbers.Zip(letters, emoji))
{
    Console.WriteLine(
        $"Number: {number} is zipped with letter: '{letter}' and emoji: {em}");
}
// This code produces the following output:
//     Number: 1 is zipped with letter: 'A' and emoji: 🤓
//     Number: 2 is zipped with letter: 'B' and emoji: 🔥
//     Number: 3 is zipped with letter: 'C' and emoji: 🎉
//     Number: 4 is zipped with letter: 'D' and emoji: 👀
//     Number: 5 is zipped with letter: 'E' and emoji: ⭐
//     Number: 6 is zipped with letter: 'F' and emoji: 💜

与前面的重载非常相似,Zip 方法投影一个元组,但这次包含三个元素。

3)、第三个重载

第三个重载接受用作结果选择器的 Func<TFirst, TSecond, TResult> 参数。 可以从压缩的序列中投影新的生成序列。

foreach (string result in
    numbers.Zip(letters, (number, letter) => $"{number} = {letter} ({(int)letter})"))
{
    Console.WriteLine(result);
}
// This code produces the following output:
//     1 = A (65)
//     2 = B (66)
//     3 = C (67)
//     4 = D (68)
//     5 = E (69)
//     6 = F (70)

使用前面的 Zip 重载,指定的函数应用于相应的元素 numbers 和 letter,生成 string 结果的序列。

4、Select 与 SelectMany

Select 和 SelectMany 的工作都是依据源值生成一个或多个结果值。 Select 为每个源值生成一个结果值。 因此,总体结果是一个与源集合具有相同元素数目的集合。 与之相反,SelectMany 生成单个总体结果,其中包含来自每个源值的串联子集合。 作为参数传递到 SelectMany 的转换函数必须为每个源值返回一个可枚举值序列。 SelectMany 连接这些可枚举序列,以创建一个大的序列。

下面两个插图演示了这两个方法的操作之间的概念性区别。 在每种情况下,假定选择器(转换)函数从每个源值中选择一个由花卉数据组成的数组。

下图描述 Select 如何返回一个与源集合具有相同元素数目的集合。

下图描述 SelectMany 如何将中间数组序列串联为一个最终结果值,其中包含每个中间数组中的每个值。

下面的示例比较 Select 和 SelectMany 的行为。 代码通过从源集合的每个花卉名称列表中提取项来创建一个“花束”。 在以下示例中,转换函数 Select<TSource,TResult>(IEnumerable<TSource>, Func<TSource,TResult>) 使用的“单值”是值的集合。 此示例需要额外的 foreach 循环,以便枚举每个子序列中的每个字符串。

class Bouquet
{
    public required List<string> Flowers { get; init; }
}

static void SelectVsSelectMany()
{
    List<Bouquet> bouquets =
    [
        new Bouquet { Flowers = ["sunflower", "daisy", "daffodil", "larkspur"] },
        new Bouquet { Flowers = ["tulip", "rose", "orchid"] },
        new Bouquet { Flowers = ["gladiolis", "lily", "snapdragon", "aster", "protea"] },
        new Bouquet { Flowers = ["larkspur", "lilac", "iris", "dahlia"] }
    ];

    IEnumerable<List<string>> query1 = bouquets.Select(bq => bq.Flowers);

    IEnumerable<string> query2 = bouquets.SelectMany(bq => bq.Flowers);

    Console.WriteLine("Results by using Select():");
    // Note the extra foreach loop here.
    foreach (IEnumerable<string> collection in query1)
    {
        foreach (string item in collection)
        {
            Console.WriteLine(item);
        }
    }

    Console.WriteLine("\nResults by using SelectMany():");
    foreach (string item in query2)
    {
        Console.WriteLine(item);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2250686.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RabbitMQ在手动消费的模式下设置失败重新投递策略

最近在写RabbitMQ的消费者&#xff0c;因为业务需求&#xff0c;希望失败后重试一定次数&#xff0c;超过之后就不处理了&#xff0c;或者放入死信队列。我这里就达到重试次数后就不处理了。本来以为很简单的&#xff0c;问了kimi&#xff0c;按它的方法配置之后&#xff0c;发…

Maven install java heap space

Maven install java heap space 打包报错 Maven install java heap space 解决&#xff1a; vm option: -Xms1024m -Xmx1024m如果 vm配置了&#xff0c;还是一样报错&#xff0c;就重新选择JRE看看是否正确&#xff0c;idea会默认自己的环境&#xff0c;导致设置vm无效&…

OpenCV_Code_LOG

孔洞填充 void fillHole(const Mat srcBw, Mat &dstBw) {Size m_Size srcBw.size();Mat TempMat::zeros(m_Size.height2,m_Size.width2,srcBw.type());//延展图像srcBw.copyTo(Temp(Range(1, m_Size.height 1), Range(1, m_Size.width 1)));cv::floodFill(Temp, Point(…

C7.5【x86汇编】底层分析范围for的执行过程

目录 1.反汇编代码 2.分析 1.栈区初始化 2.设置数组元素的值 3. 逐条分析范围for 1.arr的地址被放到[ebp-2Ch]处 2.[ebp-2Ch]指向的值被复制一份到[ebp-30h]处 3.eax暂存[ebp-2Ch]指向的值,加28h后存储到[ebp-34h]处 4.跳转指令 5.比较[ebp-30h]和[ebp-34h]指向的值,…

hue 4.11容器化部署,已结合Hive与Hadoop

配合《Hue 部署过程中的报错处理》食用更佳 官方配置说明页面&#xff1a; https://docs.gethue.com/administrator/configuration/connectors/ 官方配置hue.ini页面 https://github.com/cloudera/hue/blob/master/desktop/conf.dist/hue.ini docker部署 注意&#xff1a; …

51单片机快速入门之中断的应用 2024/11/23 串口中断

51单片机快速入门之中断的应用 基本函数: void T0(void) interrupt 1 using 1 { 这里放入中断后需要做的操作 } void T0(void)&#xff1a; 这是一个函数声明&#xff0c;表明函数 T0 不接受任何参数&#xff0c;并且不返回任何值。 interrupt 1&#xff1a; 这是关键字和参…

ffmpeg安装(windows)

ffmpeg安装-windows 前言ffmpeg安装路径安装说明 前言 ffmpeg的安装也是开箱即用的,并没有小码哥说的那么难 ffmpeg安装路径 这就下载好了! 安装说明 将上面的bin目录加入到环境变量,然后在cmd中测试一下: C:\Users\12114\Desktop\test\TaskmgrPlayer\x64\Debug>ffmpe…

HCIA笔记6--路由基础

0. 概念 自治系统&#xff1a;一个统一管理的大型网络&#xff0c;由路由器组成的集合。 路由器隔离广播域&#xff0c;交换机隔离冲突域。 1.路由器工作原理 路由器根据路由表进行转发数据包&#xff1b; 路由表中没有路由&#xff0c;直接丢弃该数据包路由表中只有一条路…

IDEA如何快速地重写方法,如equals、toString等

前言 大家好&#xff0c;我是小徐啊。我们在使用IDEA的时候&#xff0c;有时候是需要重写equals和toString等方法的。这在IDEA中已经很方便的给我们准备好了快速的操作了。今天就来讲解一下。 如何重写 首先&#xff0c;打开要重写方法的文件&#xff0c;让鼠标定位到这个文…

跨境物流市场风云变幻,集运企业需精准决策以应对挑战

跨境物流市场&#xff0c;作为全球经济的重要纽带&#xff0c;正经历着前所未有的风云变幻。据最新数据显示&#xff0c;全球海运贸易在2023年实现了2.4%的增长&#xff0c;并预计在今年年底前将再增长2%。这一增长态势虽然积极&#xff0c;但背后却隐藏着诸多挑战与不确定性。…

2024年首届数证杯 初赛wp

“数证杯”电子数据取证分析大赛致力于成为全国第一大电子数据取证分析大赛&#xff0c;面向所有网络安全从业人员公开征集参赛选手。参赛选手根据所属行业报名参赛赛道&#xff0c;比赛设置冠军、亚军、季军奖。所涉及行业包括能源、金融、通信、取证、安全等企业以及各类司法…

电机瞬态分析基础(3):空间矢量

1. 空间矢量 空间矢量的概念在交流电机分析与控制中具有非常重要的作用。将各相的电压、电流、磁链等电磁量用空间矢量表达&#xff0c;可以使三相感应电机的动态方程表达更简洁&#xff0c;为电机的分析与控制带来方便&#xff0c;并有助于对交流电机的矢量控制、直接转矩控制…

C/C++绘制爱心

系列文章 序号直达链接1C/C爱心代码2C/C跳动的爱心3C/C李峋同款跳动的爱心代码4C/C满屏飘字表白代码5C/C大雪纷飞代码6C/C烟花代码7C/C黑客帝国同款字母雨8C/C樱花树代码9C/C奥特曼代码10C/C精美圣诞树11C/C俄罗斯方块12C/C贪吃蛇13C/C孤单又灿烂的神-鬼怪14C/C闪烁的爱心15C/…

LLM应用-prompt提示:RAG query重写、相似query生成 加强检索准确率

参考&#xff1a; https://zhuanlan.zhihu.com/p/719510286 1、query重写 你是一名AI助手&#xff0c;负责在RAG&#xff08;知识库&#xff09;系统中通过重构用户查询来提高检索效果。根据原始查询&#xff0c;将其重写得更具体、详细&#xff0c;以便更有可能检索到相关信…

MTK主板_小型联发科安卓主板_行业智能终端主板基于联发科方案

MTK安卓主板是一款小巧而高效的科技产品&#xff0c;其尺寸仅为43.4mm x 57.6mm。采用了先进的联发科12nm制程工艺&#xff0c;这款主板搭载四核或八核64位A53架构的CPU&#xff0c;主频高达2.0GHz&#xff0c;不但保证了出色的计算能力&#xff0c;还实现了超低功耗的特点。系…

递归---汉诺塔

问题描述 有三根相邻的柱子&#xff0c;标号为A,B,C&#xff0c;A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘&#xff0c;要把所有盘子一个一个移动到柱子B上&#xff0c;并且每次移动&#xff0c;同一根柱子上都不能出现大盘子在小盘子上方&#xff0c;输出每次的移动。…

HTML飞舞的爱心(完整代码)

写在前面 HTML语言实现飞舞的爱心完整代码。 完整代码 <!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><title>飞舞爱心</title><style>* {margin: 0;padding: 0;}html,body {overflow: hidd…

修改训练策略,无损提升性能

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;编程探索专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年11月29日15点40分 神秘男子影, 秘而不宣藏。 泣意深不见, 男子自持重, 子夜独自沉。 论文链接 点击开启你的论文编程之旅…

@bytemd/vue掘金markdown插件预览内容有误

vue项目使用bytemd/vue 来预览字符串格式的markdown内容&#xff0c;总会多出如图的一段代码&#xff0c; 请问有没有大佬知道为什么&#xff1f; 很急&#xff0c;求教&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;