Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在不使用循环声明方式的情况下仅获取纯记录_C#_Linq - Fatal编程技术网

C# 如何在不使用循环声明方式的情况下仅获取纯记录

C# 如何在不使用循环声明方式的情况下仅获取纯记录,c#,linq,C#,Linq,我有一些买自行车的人。 这张桌子看起来像 我想得到的用户谁只买了相同的自行车。 此示例的输出必须为,因为PeopleID 2没有其他颜色 2红色 这个班是 class Foo { public String PeopleID { get; set; } public String Bicycle { get; set; } } 功能是 static void WhoBuyedSameBike(IEnumerable<Foo> foo

我有一些买自行车的人。 这张桌子看起来像

我想得到的用户谁只买了相同的自行车。 此示例的输出必须为,因为PeopleID 2没有其他颜色

2红色

这个班是

 class Foo
    {
        public String PeopleID { get; set; }
        public String Bicycle { get; set; }
    }
功能是

static void WhoBuyedSameBike(IEnumerable<Foo> foos) 
    {
        var tmpFoos = foos;
        var result = tmpFoos.GroupBy(x => x.PeopleID);
        var queryResult = new List<QueryResult>();
        foreach (var fooItem in result)
        {
            if (fooItem.Count() == tmpFoos.Count(w => w.PeopleID == fooItem.Key && w.Bicycle == "Red"))
            {
                queryResult.Add(new QueryResult { PeopleID = fooItem.Key });
            }

        }
        foreach (var item in queryResult)
        {
            Console.WriteLine($"PeopleId : {item.PeopleID}");
        }
    }
静态void whobuedsamebike(IEnumerable foos)
{
var tmpFoos=foos;
var result=tmpFoos.GroupBy(x=>x.PeopleID);
var queryResult=新列表();
foreach(结果中的项目)
{
if(fooItem.Count()==tmpFoos.Count(w=>w.PeopleID==fooItem.Key&&w.Bicycle==Red))
{
添加(新的queryResult{PeopleID=fooItem.Key});
}
}
foreach(queryResult中的var项)
{
WriteLine($“PeopleId:{item.PeopleId}”);
}
}

对于更多的声明性代码,有没有其他方法可以不使用foreach循环和Linq来获得输出

使用Linq,按每个人分组,获得每个自行车颜色的不同计数,并从计数为1的每组中选择第一个(唯一)项目

IEnumerable<Foo> result = 
    foos
    .GroupBy(foo => foo.PeopleID)
    .Where(group => group.Select(foo => foo.Bicycle).Distinct().Count() == 1)
    .Select(group => group.First());

编辑

在注释中,Harald Coppoolse建议在where语句中进行计数之前插入.Take(2)。这将更有效,因为.Count()必须枚举整个集合才能获得大小(除非它实现ICollection)。他还提出了第二种更有效的方法

然而,当我们进行此操作时,我想我会更进一步,将嵌套的Select和Distinct方法压缩到一个聚合中,结果不需要重新迭代以确定是否存在重复

foos
    .GroupBy(foo => foo.PeopleID)
    .Where(group => group.Aggregate((a,b) => a?.Bicycle == b.Bicycle ? a : null) != null)
    .Select(group => group.First());
当然,这只是为了更好地理解。当然,在了解聚合方法、terneray运算符和null条件运算符之前,首先要了解原始版本


顺便说一下。我之前没有提到,如果性能比可读性或代码优雅更重要,那么不要逃避for循环。上面的代码在没有这个限制的情况下仍然可以更有效。

您真的不应该迭代作为输入提供的任意
IEnumerable
。你不知道迭代多次是否昂贵,迭代多次是否会产生不同的结果,迭代多次是否会出现错误,等等。我同意你的观点,但这是一个面试问题。我的代码编写方式一直萦绕在我的脑海中。什么是
QueryResult
?我发现在处理嵌套或递归时,编码可能会变得困难。在这种情况下,在where语句中执行select可能会使您感到不适。所以一定要找出这些谜题来磨练你在未来面试中的技能。你是绝对正确的。这就是为什么我要努力提高我的代码编写技能。我的代码也能工作,但我必须知道更好的方法。现在我真的很高兴再次感谢。代替使用CONTUTE()来查看是否只有一个项目,考虑使用<代码>。取(2)。COUNTHER(=)=1 < /代码>,这样你就不必数别人买的所有1000辆自行车。在第二辆自行车上,你已经知道不止一辆了。效率更高:
Where not。跳过(1).Any()
@haraldcopoolse,你启发我添加一个新版本。想知道你对它的看法。
Aggregate
的使用很好,但是要知道这只适用于
AsEnumerable
<代码>可查询。实体框架不支持聚合
foreach(var foo in result) {
    Console.WriteLine($"PeopleId:{foo.PeopleID}, Bicycle:{foo.Bicycle}");
}
foos
    .GroupBy(foo => foo.PeopleID)
    .Where(group => group.Aggregate((a,b) => a?.Bicycle == b.Bicycle ? a : null) != null)
    .Select(group => group.First());