【问题标题】:IEnumerable List ManipulationIEnumerable 列表操作
【发布时间】:2014-04-09 16:53:49
【问题描述】:

我正在使用 LINQ 生成两个单独的项目列表。但是,我需要以特定方式合并这两个列表。我已经按照特定属性(序列号)进行排序并做一些其他的事情来确保一切都在它应该在的地方,但是结果集却让我望而却步。

这是我目前所拥有的:

List<item> list1 = { item1, item2, item3, item7, item8, item11, item12 }
List<item> list2 = { item4, item5, item6, 
                     item4, item5, item6, 
                     item9, item10, 
                     item9, item10 }

结果集应如下所示:

List<item> listFinal = { item1, item2, item3, 
                         item4, item5, item6, 
                         item4, item5, item6, 
                         item7, item8, 
                         item9, item10, 
                         item9, item10, 
                         item11, item12 }

基本上,无论有多少组重复项,我都需要按顺序包含重复项的最终列表。可能有一个,可能有很多,也可能没有。

有没有一种简单的方法可以在我拥有的两台设备上使用 LINQ 来完成此任务?还是我必须使用 if 语句来连接列表?

【问题讨论】:

  • 您希望它们按什么“顺序”? item 是否有表明此顺序的属性?
  • 顺序应如上面的最终列表所示。为了便于阅读,我将这些行隔开。
  • @EricOlson 你想按他们的名字对你的项目进行排序吗?或某种财产/领域?你能给我们更多关于物品类别的细节吗?
  • 您上面的代码按变量名显示顺序。您需要提供一个值。
  • 值是什么并不重要。它可以是任何东西。我有我需要的值,并按它们排序。每个项目都有一个序列号,这就是我正在使用的。上面的代码被高度简化了。

标签: c# linq list ienumerable


【解决方案1】:

只需使用Concat 然后OrderBy

var resultList = list1.Concat(list2).OrderBy(x => x.Something).ToList();

更新:根据你的cmets,这里有一个扩展方法,你可以使用。由于你没有告诉我们你的类是什么样子,我只是创建一个类,例如一个接口。

public static IEnumerable<T> ConcatItems<T>(this IList<T> source, IList<T> dest)
        where T: ISequence
{
     int index = 0;

     foreach (var x in source)
     {
         if (x.SequenceNumber < dest[index].SequenceNumber)
         {
             dest.Insert(index, x);
             continue;
         }
         while(x.SequenceNumber > dest[index].SequenceNumber) index++;

         if (index != dest.Count - 1 && x.SequenceNumber == dest[index].SequenceNumber)
         {
             while (index != dest.Count -1 && 
                 Math.Abs(dest[index].SequenceNumber - dest[index + 1].SequenceNumber) == 1) index++;

              if (index != dest.Count - 1) dest.Insert(index, x);
              else dest.Add(x);
              continue;
         }
         dest.Insert(index, x);
     }

     return dest;
} 

接口和类:

public interface ISequence
{
    int SequenceNumber { get; set; }
}
class Item : ISequence
{
    public int SequenceNumber { get; set; }

    public Item(int number)
    {
        SequenceNumber = number;
    }
}

这里是用法(list1list2List&lt;Item&gt;):

var result = list1.ConcatItems(list2);

该方法完全符合您的要求,但您应该根据自己的情况实施它,这部分取决于您...

这是LINQPad上的演示:

列表1:

列表2:

输出:

最后一点:此方法假定您的项目已订购。如果不是,请先对您的项目进行排序,然后调用该方法:

Comparison<Item> comp = (x, y) => x.SequenceNumber.CompareTo(y.SequenceNumber);
list1.Sort(comp);
list2.Sort(comp);
var result = list1.ConcatItems(list2);

【讨论】:

  • 别忘了给结果赋值。
  • 嗯...好的。让我看看这是否可行。我不认为它会因为我必须单独按顺序获得重复的集合。像这样:4、5、6、4、5、6。这个语句看起来会给我 4、4、5、5、6、6。不完全是我需要的。
  • @Selman22 - 这看起来不错。让我试试看。谢谢!
  • @EricOlson 最后出现问题,现在我修复了它。现在它将最后 11-12 附加到第二个列表的末尾。
  • @Selman22 - 谢谢!这是一个巨大的帮助。我很欣赏你在这方面的工作。我会将这些信息纳入我的测试并尝试一下。再次感谢您!
【解决方案2】:

您可以使用列表中的 AddRange 方法来组合另一个相同类型的列表。这不会完成你想要做的事情吗?

【讨论】:

  • 添加范围?好的……这可能行得通……我得稍微调整一下才能试一试,但这听起来很对。
  • Eric,您基本上只需执行“list1.AddRange(list2);”,这将取代您的 listFinal。这应该对你有用!
【解决方案3】:

请试试这个

var list = list1.Concat(list2);

【讨论】:

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