从列表内的列表中按项目排序

时间:2013-01-14 03:52:34

标签: c# .net linq sorting

我有以下课程的项目列表:

public class MonthlyConsumption : UserData
{
    public string Unit { get; set; }

    public List<DailyConsumption> DailyConsumptions { get; set; }
}

public class DailyConsumption
{
    public DateTime Day { get; set; }
    public double? Value { get; set; }
}

所以你可以看到,我有一个项目列表,其中每个项目也有里面的日期列表。

我的问题是如何通过内部列表中的specyfic元素来命令我的主列表。

示例:我有MonthlyConsumption类型的列表。该列表的每个元素都有DailyConsumption类型的集合,此集合从今年1月开始是第10天。如何在1月1日之前订购我的主列表?

更新: 我担心我的问题是错误的,我真正想做的是订购我的类型MonthlyConsumption列表,其中每个项目都有他自己的类型DailyConsumption 按特定日期的值列表,所以如果每个我的清单中的项目从1月1日到10日在他的内部集合中有10天,我想按照jan 1中的值排序我的主列表。

更新 我试过了

return monthlyConsumption.OrderBy(x => x.DailyConsumptions.Where(y => y.Day.Day == 1))
                         .ToList();

但它给了我至少一个对象必须实现IComparable

3 个答案:

答案 0 :(得分:4)

我没有测试过,但我相信你可以用Linq做到。

假设“monthlyConsumptions”是List<MonthlyConsumption>

monthlyConsumptions.OrderBy(mc => mc.DailyConsumptions.Min(dc => dc.Day));

这将最早MonthlyConsumption订购DailyConsumption的列表。

答案 1 :(得分:1)

如果我理解正确,也许这样的事情就是你所追求的:

var targetDay = DateTime.Now; //set to Jan 1st
var result =
    monthylConsumptions.OrderBy(
        x =>
        x.DailyConsumptions.Where(y => y.Day.Date == targetDay.Date).Select(z => (!z.Value.HasValue ? 0 : z.Value.Value)).SingleOrDefault());
根据您的示例,

“targetDay”应设置为1月1日。

这将按指定日期的值按升序排序,并在每月特定月份中考虑默认值。

修改 我刚刚测试了下面的单元测试,它通过了,没有显示你所描述的错误:

[TestFixture]
public class LinqSortTest
{
    public class MonthlyConsumption
    {
        public string Unit { get; set; }

        public List<DailyConsumption> DailyConsumptions { get; set; }
    }

    public class DailyConsumption
    {
        public DateTime Day { get; set; }
        public double? Value { get; set; }
    }

    [Test]
    public void SomeTest()
    {
        var targetDay = new DateTime(2013, 1, 1);
        var monthlyConsumptions = new List<MonthlyConsumption>();
        monthlyConsumptions.Add(new MonthlyConsumption
            {
                Unit = "first",
                DailyConsumptions = new List<DailyConsumption>
                    {
                                new DailyConsumption { Day = new DateTime(2013, 1, 1), Value = 5 },
                                new DailyConsumption { Day = new DateTime(2013, 1, 5), Value = 100 }
                    }
            });
        monthlyConsumptions.Add(
            new MonthlyConsumption
                {
                    Unit = "second",
                    DailyConsumptions =
                        new List<DailyConsumption>
                            {
                                new DailyConsumption { Day = new DateTime(2013, 1, 1), Value = 2 },
                                new DailyConsumption { Day = new DateTime(2013, 1, 5), Value = 1 }
                            }
                });

        var result =
            monthlyConsumptions.OrderBy(
                x =>
                x.DailyConsumptions.Where(y => y.Day.Date == targetDay.Date).Select(
                    z => (!z.Value.HasValue ? 0 : z.Value.Value)).SingleOrDefault()).ToList();

        Assert.AreEqual("second", result[0].Unit);
    }
}

正如您所看到的,Assert确认第二项确实放在第一位,因为“第二”的Jan 1值低于“第一”。

答案 2 :(得分:1)

尝试:

monthlyConsumptions
    .SelectMany(mc => mc.DailyConsumptions)
    .Where(dc = > dc.Day.Date.Day == 1 && dc.Day.Date.Month == 1)
    .OrderBy(dc => dc.Value)
    .Select(dc => dc.MonthlyConsumption);

这将获取所有DailyConsumptions的所有MonthlyConsumptions,然后仅过滤1月1日的那些,按Value排序,而不是从中获取任何数据,它返回父实体这是MonthlyConsumption

所以你按照自己的意愿订购IQuerable<MonthlyConsumption>

编辑:这将在LINQ to Entities中运行,在您的情况下可能并非遗憾,除非您在DailyConsumption中拥有名为MonthlyConsumption的父属性。