【问题标题】:c# - using SelectMany to merge multiple listsc# - 使用 SelectMany 合并多个列表
【发布时间】:2019-04-15 11:45:45
【问题描述】:

截至目前,我使用以下代码合并两个List<string> 列表并按时间戳对它们进行排序

var list = report[0];  
var list2 = report[1];
var result = list
    .Union(list2)
    .Select(x =>
    {  return new {Log = x, Time = TimeSpan.Parse(x.Split(' ')[0])}; })
    .OrderBy(x => x.Time)
    .ToList(); 

现在的问题是我必须处理两个以上的列表,最多为 n。我查看了SelectMany 示例,但它似乎不支持与Select 相同的功能。我计划这样做的另一种方法是使用 foreach 循环,但这似乎不是一种有效的方法,尤其是当列表变大时。
编辑(添加示例数据和预期结果):强>
示例 list1 可能如下所示:
11:03:01:003 INFO some event has occurred 11:03:31:004 DEBUG another event has occurred 11:04:01:015 INFO third event has occurred
示例 list2 可能如下所示:
11:03:16:003 INFO fourth event has occurred 11:03:32:025 DEBUG fifth event has occurred 11:03:54:023 INFO sixth event has occurred
因此,可以有多个这样的列表。这两个列表的预期合并将如下所示:
11:03:01:003 INFO some event has occurred 11:03:16:003 INFO fourth event has occurred 11:03:31:004 DEBUG another event has occurred 11:03:32:025 DEBUG fifth event has occurred 11:03:54:023 INFO sixth event has occurred 11:04:01:015 INFO third event has occurred

【问题讨论】:

  • 您能提供一些示例数据并期待结果吗?
  • 你不能只做list1.Union(list2).Union(list3).Union(list4)之类的吗?

标签: c# linq merge


【解决方案1】:

不知道为什么其他答案有额外的.Select

var result = report
       .SelectMany(l => l, (l, x) => new { Log = x, Time = TimeSpan.Parse(x.Split(' ')[0]) })
       .Distinct().OrderBy(x => x.Time).ToList(); 

【讨论】:

  • 因为report 的成员显然是字符串的可枚举。
  • report 是一个IEnumerable<List<string>> (根据OP:“我使用以下代码合并两个List<string> 列表”),所以在你的代码中@ 987654327@ 是List<string>,你不能做x.Split()。您必须首先将所有列表扁平化为一个列表,这就是 .SelectMany() 所做的,然后然后您可以在其上执行 .Select()
  • 仍然不对,不会像Union 那样删除重复项。
【解决方案2】:

我假设reportIEnumerable<string>IEnumerable。所以你需要这样的东西:

report.SelectMany(l => l.Select(x => new {Log = x, Time = TimeSpan.Parse(x.Split(' ')[0])}))
    .OrderBy(x => x.Time)
    .ToList();

SelectMany 将合并l.Select 的所有结果,然后按时间排序。

编辑:

既然已经指出Union会删除重复项,那么需要加上Distinct才能得到同样的结果:

report.SelectMany(l => l.Select(x => new {Log = x, Time = TimeSpan.Parse(x.Split(' ')[0])}))
    .Distinct()
    .OrderBy(x => x.Time)
    .ToList();

【讨论】:

  • Union 删除重复项。
【解决方案3】:

对此有多种解决方案,其中之一可能是:

List<IEnumerable<string>> allLists = new List<IEnumerable<string>>();
            allLists.Add(report[0]);
            allLists.Add(report[1]);
            allLists.Add(report[2]);

            var result = allLists.SelectMany(l => l.Select(x => new
            {
                Log = x,
                Time = TimeSpan.Parse(x.Split(' ')[0])
            })).OrderBy(x => x.Time)
            .ToList();

【讨论】:

  • Union 删除重复项。
  • 据我所知,作者说report[0] 是一个List 以及report[1]。事实上,他可以直接处理报告(如果它是一个 IEnumerable),而不是创建一个 allLists 变量。
【解决方案4】:

可以在这里使用SelectMany

// suppose reports is of type List<List<SomeClass>>
reports.SelectMany(x => x)
    .Select(x =>
        {  return new {Log = x, Time = TimeSpan.Parse(x.Split(' ')[0])}; })
    .OrderBy(x => x.Time)
    .ToList(); 

添加.Distinct 调用将使其具有与Union 相同的效果:

reports.SelectMany(x => x).Distinct()
    .Select(x =>
        {  return new {Log = x, Time = TimeSpan.Parse(x.Split(' ')[0])}; })
    .OrderBy(x => x.Time)
    .ToList(); 

或者,继续使用Union

IEnumerable<SomeClass> query = reports[0];
for (int i = 1 ; i < reports.Length ; i++) {
   query = query.Union(reports[i]);
}

【讨论】:

    猜你喜欢
    • 2017-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多