使用Linq

时间:2018-09-05 21:37:20

标签: c# linq

我有一个这样的对象列表:

public class ExceptionFolderEntries
{
    public int Id { get; set; }

    public string Data { get; set; }

    public DateTime? StartTime { get; set; }
    public DateTime? EndTime { get; set; }

}

无论是否为结束时间的开始时间,我都在尝试获取下一个“时间”,以便我可以采取措施。 我知道如何使用基于StartTime或EndTime的LINQ来排序列表,但是不知道如何合并数据,然后对新合并的列表进行排序。

示例: 带有数据:

  

“ ABC”,“ 1/1/2018 01:00”,“ 1/2/2018 13:00”

     

“ MNO”,“ 1/1/2018 01:30”,“ 1/1/2018 08:00”

     

“ XYZ”,“ 1/1/2018 09:00”,“ 1/2/2018 13:00”

会导致

  

ABC 1/1 01:00

     

MNO 1/1 01:30

     

MNO 1/1 08:00

     

XYZ 1/1 09:00

     

ABC 1/2   13:00

     

XYZ 1/2 13:00

有什么建议吗?

4 个答案:

答案 0 :(得分:1)

您可以尝试创建两个FolderEntries新创建集合,一个用于StartTime,另一个用于EndTime,然后使用linq Concat组合两个集合。然后做order by

public class FolderEntries {
    public string Data { get; set; }
    public DateTime? FolderDateTime { get; set; }
}

var result =
  (from s1 in list select new FolderEntries(){
      Data = s1.Data,
      FolderDateTime = s1.StartTime
  }).Concat
  (from s2 in list select new FolderEntries {
      Data = s2.Data,
      FolderDateTime = s2.EndTime
  }).OrderBy(x=>x.FolderDateTime);

结果

ABC 1/1/2018 1:00:00 AM
MNO 1/1/2018 1:30:00 AM
XYZ 1/1/2018 9:00:00 AM
MNO 1/1/2018 1:08:00 PM
ABC 1/2/2018 1:00:00 PM
XYZ 1/2/2018 1:00:00 PM

c# online

答案 1 :(得分:1)

我的答案也许与Eriks答案太相似,但是一种解决方法是选择一个新的ExceptionFolderEntries(由于它只代表一个项目,因此应真正重命名为ExceptionFolderEntry)。每个非空的StartTimeEndTime,保留我们正在读取的那个(开始或结束),并保留另一个字段null

然后,您可以按非空值StartTime ?? EndTime来订购新的(可调整的)列表。

例如:

var sortedItems =
    // First select a new item for all non-null StartTimes
    items.Where(i => i.StartTime.HasValue) 
        .Select(i => new ExceptionFolderEntries {Data = i.Data, StartTime = i.StartTime})

        // Then concat with a new item for all non-null EndTimes
        .Concat(items
            .Where(i => i.EndTime.HasValue) 
            .Select(i => new ExceptionFolderEntries {Data = i.Data, EndTime = i.EndTime}))

        // And finally, order by the non-null field
        .OrderBy(i => i.StartTime ?? i.EndTime)
        .ToList();

// Now we can write out the data and the non-null field for each item
sortedItems.ForEach(i => Console.WriteLine($"{i.Data} {i.StartTime ?? i.EndTime}"));

输出

enter image description here

在上面的示例中,items初始化为:

var items = new List<ExceptionFolderEntries>
{
    new ExceptionFolderEntries
    {
        Data = "ABC",
        StartTime = DateTime.Parse("1/1/2018 01:00"),
        EndTime = DateTime.Parse("1/2/2018 13:00")
    },
    new ExceptionFolderEntries
    {
        Data = "MNO",
        StartTime = DateTime.Parse("1/1/2018 01:30"),
        EndTime = DateTime.Parse("1/1/2018 08:00")
    },
    new ExceptionFolderEntries
    {
        Data = "XYZ",
        StartTime = DateTime.Parse("1/1/2018 09:00"),
        EndTime = DateTime.Parse("1/2/2018 13:00")
    },
};

答案 2 :(得分:0)

ExceptionFolderEntries[] entries = [];
entries.Select(e => new DateTime?[] {e.StartTime, e.EndTime).SelectMany(dt => dt).OrderBy(//ordery by logic)

首先将日期时间选择到一个数组中(创建一个数组数组),然后使用select many将其展平。

编辑:也可以缩短

ExceptionFolderEntries[] entries = [];
entries.SelectMany(e => new DateTime?[] {e.StartTime, e.EndTime).OrderBy(//ordery by logic)

答案 3 :(得分:0)

首先,您的课程可能不应以(s)结尾,因为它不是集合,因此在示例中将使用ExceptionFolderEntry

我可能会做类似的事情:

class ExceptionFolderEntryMeta
{
  public ExceptionFolderEntry ExceptionFolderEntry { get; set; }
  public DateTime SortBy { get; set; }
  public bool IsStartTime { get; set; }
}

var exceptionFolderEntries = new List<ExceptionFolderEntry>();

var mergeList = exceptionFolderEntries 
  .Where(efe => efe.StartTime.HasValue)
  .Select(efe => new ExceptionFolderEntryMeta
    {
      ExceptionFolderEntry  = efe,
      SortBy = efe.StartTime,
      IsStartTime = true,
    })
  .Concat(exceptionFolderEntries 
    .Where(efe => efe.EndTime.HasValue)
    .Select(efe => new ExceptionFolderEntryMeta
      {
        ExceptionFolderEntry  = efe,
        SortBy = efe.EndTime,
        IsStartTime = false,
     }))
  .OrderBy(efem => efem.SortBy)
  .ToList())

我创建了新类,以便进行正确的排序并指示它是开始时间还是结束时间(因为您可能需要在某个时候知道这一点)。我还考虑到您已将这些属性创建为可为空,因此,如果一个属性为null,则它仅出现一次,如果两个属性都为null,则永远不会出现。