我有一个包含两个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
所以这种方法有效,但有没有更有效的方式来执行此查询?
答案 0 :(得分:3)
试试这个:
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 }},
};
=&GT;这给出了(2,1),(4,1),(2,3),(4,3)......这是预期的结果吗? (如果是,我的请求不起作用)
答案 1 :(得分:0)
如果您实施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