簡體   English   中英

根據兩個子列表的連接獲取單個列表

[英]Get Single List Based on Join of Two Sub Lists

我有一個包含兩個List子屬性的Items列表,我需要獲取所有(唯一)值,這些值是這兩個子屬性被聯接(但僅在其父類中聯接)的結果。 下面是一個人為的示例:

public class Calendar
{
    public List<int> Months { get; set; }
    public List<int> Days { get; set; }
    public int Id { get; set; }

    public Calendar(int id)
    {
        Months = new List<int>();       
        Days = new List<int>();
        this.Id = id;
    }
}

我有一個Calendar對象列表,我需要從整個集合中獲取月/日組合的列表。 我設法通過將兩個SelectMany選項結合在一起來做到這一點:

var years = new List<Calendar>();

var cal2001 = new Calendar(1);  
cal2001.Months = new List<int>() { 1, 2};
cal2001.Days = new List<int>() { 1, 6 };
years.Add(cal2001);

var cal2002 = new Calendar(2);  
cal2002.Months = new List<int>() { 2, 4};
cal2002.Days = new List<int>() { 6, 15 };
years.Add(cal2002);

var items = (from M in years.SelectMany(Y => Y.Months, (Y, result) => new { Month = result, Id = Y.Id })
            join D in years.SelectMany(Y => Y.Days, (Y, result) => new { Day = result, Id = Y.Id }) on M.Id equals D.Id
            select new { Day = D.Day, Month = M.Month }).Distinct();

items.Dump(); //Dump items to output in Linqpad.

這給出了所需的輸出:

Day  Month
1    1
6    1
1    2
6    2
15   2
6    4
15   4

因此,此方法有效,但是執行此查詢是否有更有效的方式?

嘗試這個:

years.SelectMany(y=> from d in y.Days
                    from m in y.Months
                   select new{d,m})  // cross join
    .Distinct()
    .Dump();

這給出了相同的輸出。

此外,您的要求真的是您想要實現的嗎? 如果同一年有多個日歷,它會給出時髦的結果。 例如,嘗試您的請求:

var years = new []{
    new Calendar(2001){ Months = { 1 }, Days= { 2 }},
    new Calendar(2001){ Months = { 3 }, Days= { 4 }},
};

=>這給出(2,1),(4,1),(2,3),(4,3)...這是預期的結果嗎? (如果是,我的請求無效)

如果實現IEqualityComparer ,則可以使用Distinct清除重復項。 我介紹了一個名稱類DateEntry ,它對應於您擁有的匿名類型。 我還實現了IComparable以便對結果進行排序。

public class DateEntryComparer : IEqualityComparer<DateEntry>
{   
    public bool Equals(DateEntry lhs, DateEntry rhs)
    {
        return lhs.Day == rhs.Day && lhs.Month == rhs.Month;
    }

    public int GetHashCode(DateEntry entry)
    {
        return entry.Day.GetHashCode() ^ entry.Month.GetHashCode();
    }
}

public class DateEntry : IComparable<DateEntry>
{
    public int Day {get;set;}
    public int Month {get;set;} 

    public int CompareTo(DateEntry entry)
    {
        var result = Month.CompareTo(entry.Month);

        if(result == 0)
        {
            result = Day.CompareTo(entry.Day);
        }

        return result;
    }
}

public class Calendar
{
    public List<int> Months { get; set; }
    public List<int> Days { get; set; }
    public int Year { get; set; }

    public Calendar(int year)
    {
        Months = new List<int>();       
        Days = new List<int>();
        Year = year;
    } 

    public IEnumerable<DateEntry> GetDateEntries()
    {
        return from d in Days 
               from m in Months
               select new DateEntry { Day = d, Month = m };
    }
}

然后,您可以執行以下操作:

var items = years.SelectMany(y => y.GetDateEntries()).Distinct(new DateEntryComparer()).OrderBy(x => x);
    items.Dump(); //Dump items to output in Linqpad.

輸出:

1 1 
6 1 
1 2 
6 2 
15 2 
6 4 
15 4 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM