简体   繁体   English

Linq比较C#中的两个集合

[英]Linq to compare two collections in C#

I want to compare two collections in C# that I'm currently doing using nested "for" loop. 我想比较C#中的两个集合,我目前正在使用嵌套的“for”循环。 is there a way in Linq to do the same which will be quicker and more efficient? 在Linq有没有办法做同样的事情会更快更有效? here is my current code which works perfectly just looking for an efficient way: 这是我目前的代码,它只是寻找一种有效的方法:

OrgCollection myYears = Org.RetrieveDistinctYear();
if (myYears.Count > 0)
{
AcademicYearCollection allYears = AcademicYear.RetrieveAll();
for (int i = 0; i < myYears.Count; i++)
{
    for (int j = 0; j < allYears.Count; j++)
    {
        if (myYears[i].AcademicYearCode == allYears[j].Code)
        {
        ddlYear.Items.Insert(0, new ListItem(allYears[j].Name,allYears[j].Code));
        break;
        }
    }
}
}

I want to compare "Code" from AcademicYearCollection with the "AcademicYearCode" property in OrgCollection & if it is the same then add it in the Dropdownlist "ddlYear". 我想将AcademicYearCollection中的“Code”与OrgCollection中的“AcademicYearCode”属性进行比较,如果它是相同的,则将其添加到Dropdownlist“ddlYear”中。

Thanks in advance. 提前致谢。

You can do it in LINQ, which gives shorter code. 您可以在LINQ中执行此操作,从而提供更短的代码。 To know if it is more efficient or not you would have to profile it. 要知道它是否更有效,您必须对其进行分析。 I think that linq's join operator uses some kind of hash buckets inernally which should give better performance, especially if the collections are large. 我认为linq的join运算符使用某种类型的散列桶,这应该可以提供更好的性能,尤其是在集合很大的情况下。 Your current solution is O(N^2) which will quickly degrade if the number of options increases. 您当前的解决方案是O(N ^ 2),如果选项数量增加,它将迅速降级。

OrgCollection myYears = Org.RetrieveDistinctYear();
AcademicYearCollection allYears = AcademicYear.RetrieveAll();

var items = from y in myYears
            join ay in allYears
            on y.Code equals ay.AcademicYearCode
            select new { ay.Name, ay.Code }
OrgCollection myYears = Org.RetrieveDistinctYear();
if (myYears.Count > 0)
{
    AcademicYearCollection allYears = AcademicYear.RetrieveAll();
    for (int i = 0; i < myYears.Count; i++)
    {
         if (allYears[j].Any(allY => allY ==  myYears[i].AcademicYearCode ))
            {
                ddlYear.Items.Insert(0, new ListItem(allYears[j].Name, allYears[j].Code));
                break;
            }

    }
}

This could be an option but i think the extension method 'any' works the same way by doing an iteration. 这可能是一个选项,但我认为扩展方法'any'通过迭代工作方式相同。

How about this 这个怎么样

var allYears = AcademicYear.RetrieveAll().ToDictionary(y => y.Code, y.Name);

ListItem match = null;
foreach(var year in Org.RetrieveDistinctYear())
{
    if (allYears.HasKey(year.AcademicYearCode)
    {
        match = new ListItem(
                       allYears[year.AcademicYearCode], 
                       year.AcademicYearCode);
        break;
    }
}

if (match != null)
{
    ddlYear.Items.Insert(0, match); 
}

Using a Dictionary here provides superior performance and the further down the Org.RetrieveDistinctYear results the match is, the more benefit there will be. 在这里使用Dictionary提供了卓越的性能,并且在匹配的Org.RetrieveDistinctYear结果的下方,将会带来更多的好处。 If the results of RetrieveDistinctYear are often short or the match is at the top the overhead of creating the dictionary will make the code unesscessarily slow. 如果RetrieveDistinctYear的结果通常较短或匹配位于顶部,则创建字典的开销将使代码失败。


EDIT 编辑

Or this approach 或者这种方法

var allYears = AcademicYear.RetrieveAll().ToDictionary(y => y.Code, y.Name);

var matchingCode = Org.RetrieveDistinctYear()
    .Select(y = y.AcademicYearCode)
    .FirstOrDefault(code => allYears.HasKey(code));

if (!string.IsEmptyOrWhitespace(matchingCode))
{
    ddlYear.Items.Insert(0, new ListItem(
                                 allYears[matchingCode], 
                                 matchingCode)); 
}

This solution has similar speed and efficiency to your original solution, but it can be parallelized by changing from y in myYears to from y in myYears.AsParallel() to possibly speed it up. 此解决方案与原始解决方案具有相似的速度和效率,但它可以通过from y in myYearsfrom y in myYears.AsParallel()更改from y in myYears from y in myYears.AsParallel()来并行化,从而可能加快速度。

OrgCollection myYears = Org.RetrieveDistinctYear();
AcademicYearCollection allYears = AcademicYear.RetrieveAll();

var items = from y in myYears
            let match = allYears.FirstOrDefault( ay => y.AcademicYearCode == ay.Code)
            where match != null
            select new ListItem(match.Name, match.Code);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM