【问题标题】:Merge two lists in C#在 C# 中合并两个列表
【发布时间】:2014-08-30 09:50:39
【问题描述】:

我想将两个具有不同属性的列表合并到一个列表中,但是在合并它时,我想检查在这个特定示例中是否存在两个列表中的确切日期,如果有,我想要从该元素中获取两个属性,并将它们合并到另一个列表中的一个元素中

清单 1:

List<object> r1 = (from x in sp1 select new 
                   { 
                     x.Imported, 
                     x.Period 
                   }).ToList<object>();

L1 结果:

清单 2:

List<object> r2 = (from x in sp2 select new 
                   { 
                     x.Dissolution, 
                     x.Period 
                   }).ToList<object>();

L2 结果:


想要的结果:

目前,这就是我合并 r1 和 r2 的方式:

 List<object> r3 = new List<object>(r1.Concat(r2));

【问题讨论】:

  • 请使用强类而不是匿名类。
  • 这与问题无关;)
  • 我认为 stack 的目标之一是挑战 :)
  • @ToTa:这就是它的评论。
  • @NikhilAgrawal 是的,但这种类型的评论远离主要问题,我担心人们厌倦了阅读那种类型的 cmets,也许我们可以在这里批评我为什么使用List 而不是 IList 但有什么意义,这能解决这个特殊问题吗..

标签: c# list merge


【解决方案1】:

创建字典

Dictionary MyDict<String, List<Object>>;

MyDict[object.Perdiod].Add(object);

对于每个日期,字典中都会有一个条目,它会在这个“日期索引”处保存一个在那个时期发生的所有对象的列表。

IMO 最简单的方法,它不需要对添加的每个条目进行 O(n) 检查

只要确保在添加数据时它不是空 IE

MyDict[Object.Period] != null

另外,Nikhil Agrawal 是否说过我不会使用 Object 来保存事物列表……感觉不对,而且容易出错。您可能想要声明一个抽象类,该类将像接口一样使用,或者只是这些项目(对象)的接口。

【讨论】:

    【解决方案2】:

    您可以将它们转换为相同的类型并使用类似的东西

    r1
    .Select(x => new { Imported = x.Imported, Dissolution = null, Period = x.Period)
    .Concat(
        r2.Select(x => new { Imported = null, Dissolution = x.Dissolution, Period = x.Period))
    .GroupBy(x => x.Period)
    .Select(x => new { Imported = x.Max(e => e.Imported),
                       Dissolution = x.Max(e => e.Dissolution),
                       Period = x.Key);
    

    【讨论】:

      【解决方案3】:

      AFAK 你需要反射来实现这一点,因为匿名类型的名称是在编译时分配的,这里有一个关于如何实现你想要的例子的例子

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Reflection;
      using System.Text;
      using System.Xml.Linq;   
      using System.Threading.Tasks;
      
      namespace ConsoleApplication1
      {
          class Program
          {
              static void Main(string[] args)
              {
                  List<ImportedType> sp1 = new List<ImportedType>();
                  List<DissolutionType> sp2 = new List<DissolutionType>();
                  sp1.AddRange( new ImportedType[]{new ImportedType() { Imported = 2, Period = "2024-02" }, new ImportedType() { Imported = 2, Period = "2014-11" }, new ImportedType() { Imported = 2, Period = "2024-12" }});
                  sp2.AddRange(new DissolutionType[] { new DissolutionType() { Dissolution = 2, Period = "2024-02" }, new DissolutionType() { Dissolution = 2, Period = "2034-02" }, new DissolutionType() { Dissolution = 2, Period = "2024-12" } });    
                  var  r1 = (from x in sp1
                                     select new
                                     {
                                         x.Imported,
                                         x.Period
                                     }).ToList<object>();
                  var r2 = (from x in sp2
                                     select new
                                     {
                                         x.Dissolution,
                                         x.Period
                                     }).ToList<object>();                
                  var r3 = r1.Concat(r2).Except(r1.Where(res =>
                      {    
                          object vp2 = r2.SingleOrDefault(res2 => GetValue(res2) == GetValue(res));
                          if (vp2!=null)
                          {
                              return true; 
                          }    
                          return false;
                      }));        
              }
      
              private static object GetValue(object res)
              {
                  Type t = res.GetType();
                  PropertyInfo p = t.GetProperty("Period");
                  object v = p.GetValue(res, null);
                  return v; 
              }
          }
      }
      

      //这里我假设你实现了2个这样的类

      public class ImportedType
          {
              public int Imported { get; set;  }
              public string Period { get; set; }
      
          }
          public class DissolutionType
          {
              public int Dissolution { get; set; }
              public string  Period { get; set; }
      
          }
      

      结果

      【讨论】:

        【解决方案4】:

        我同意 Nikhil Agrawal 的观点,因为现在确实需要对代码进行一些修复,因为使用匿名类型确实很难,尤其是因为它们已被强制转换为对象。

        忽略这一点,并接受它作为挑战(使用匿名类型转换为对象),这就是我想出的:

        合并的代码执行完全外连接:

                Func<object, object> getPeriodKey = first =>
                {
                    var periodProperty = first.GetType().GetProperty("Period");
                    return periodProperty.GetValue(first);
                };
        
                var temp = r1.GroupJoin(r2, getPeriodKey, getPeriodKey, (obj, tInner) =>
                {
                    dynamic right = tInner.FirstOrDefault();
        
                    if (right == null)
                        return (object)(new
                        {
                            Period = ((dynamic)obj).Period,
                            Imported = ((dynamic)obj).Imported,
                        });
                    else
                        return (object)(new
                        {
                            Period = ((dynamic)obj).Period,
                            Imported = ((dynamic)obj).Imported,
                            Dissolution = (int?)right.Dissolution,
                        });
        
                });
        
                var merged = temp.Union(r2, new RComparer());
        

        所需的比较器如下:

            class RComparer : IEqualityComparer<object>
            {
                public bool Equals(object x, object y)
                {
                    var xPeriodProperty = x.GetType().GetProperty("Period");
                    var yPeriodProperty = y.GetType().GetProperty("Period");
        
                    if (xPeriodProperty != null && yPeriodProperty != null)
                    {
                        var xPeriod = (string)xPeriodProperty.GetValue(x);
                        var yPeriod = (string)yPeriodProperty.GetValue(y);
                        return xPeriod == yPeriod;
                    }
                    else
                        return base.Equals(y);
                }
        
                public int GetHashCode(object obj)
                {
                    var periodProperty = obj.GetType().GetProperty("Period");
        
                    if (periodProperty != null)
                        //This will essentially hash the string value of the Period
                        return periodProperty.GetValue(obj).GetHashCode();
                    else
                        return obj.GetHashCode();
                    ;
                }
            }
        

        【讨论】:

          猜你喜欢
          • 2021-10-06
          • 1970-01-01
          • 2020-09-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-20
          • 2012-03-20
          相关资源
          最近更新 更多