如何将这个C# Linq查询语法转换为Linq方法lambda语法?

icnyk63a  于 2023-02-20  发布在  C#
关注(0)|答案(1)|浏览(179)
public Dictionary<string, Dictionary<int, List<int>>> fuBenNPCDictionary;
。。。something;
IEnumerable<(string fuben, int pos)> query = from string fuben in fuBenNPCDictionary.Keys
                                                         let fubendict = fuBenNPCDictionary[fuben]
                                                         from int pos in fubendict.Keys
                                                         where fubendict[pos].Contains(npc.ID)
                                                         select (fuben, pos);
            if (query.Count() > 0)
                foreach ((string fuben, int pos) in query)
                {
                    placestr = "在" + jsonData.instance.SceneNameJsonData[fuben]["MapName"].str.ToCN() + "的第" + pos.ToString() + "位置";
                }

这个查询原来是手工foreach,后来VS把它变成了Linq形式,我不是很擅长linq,想把它转换成Linq方法lambda语法。

1dkrff03

1dkrff031#

IEnumerable<(string key, int pos)> query = fuBenNPCDictionary.Keys
    .SelectMany(fuben => fuBenNPCDictionary[fuben]
        .Where(fubenDict => fubenDict.Value.Contains(npc.ID))
        .Select(fubenDict => (fuben, fubenDict.Key)));

简要说明

如果您不熟悉SelectMany,那么现在考虑一下这段代码将做什么可能会更容易:

IEnumerable<IEnumerable<(string key, int Key)>> query2 = fuBenNPCDictionary.Keys
    .Select(fuben => fuBenNPCDictionary[fuben]
        .Where(fubenDict => fubenDict.Value.Contains(npc.ID))
        .Select(fubenDict => (fuben, fubenDict.Key)));

首先我们从fuBenNPCDictionary.Keys上的一个Select开始,获取每个字符串键,并将其Map到后续代码的返回值,换句话说,对于dict中的每个键,执行某种计算或过程,然后给予我一个新的列表,其中包含该过程的返回值。
在这个Select中,我们可以考虑一下我们对其中一个键做了什么,我们将得到这个键对应的值:fuBenNPCDictionary[fuben],即现在的Dictionary<int, List<int>>。我们希望过滤此处的值,使其仅包含相关的List<int>,因此我们将使用Where。接下来,我们希望将过滤后的ListSelect作为元组(fuben, fubenDict.Key)。注意,我们从当前Select的直接作用域中获取fubenDict,但是我们可以从父对象Select的作用域中获取fuben,如果我们编写如下语句(为了简洁起见,省略了Where),就更容易看出这是有效的:

fuBenNPCDictionary.Keys.Select(fuben => 
{
    return fuBenNPCDictionary[fuben]
        // Note this is still inside the curly braces in which `fuben` is still in scope.
        .Select(fubenDict => (fuben, fubenDict.Key));
});

综上所述,最后剩下的就是query2包含了我们不希望的额外嵌套级别:它的类型是IEnumerable<IEnumerable<(string key, int Key)>>而不是IEnumerable<(string key, int pos)>,所以不是一个列表,而是一个列表的列表,答案是把外部的Select改为SelectMany,一个简单的SelectMany的例子是,如果你有一个数组,看起来像

[ [1, 2], [1] ]

您可以执行SelectMany(x => x)以获得[1, 2, 1],从而将交错数组扁平化为单个数组。

相关问题