在C#中合并两个列表

时间:2014-07-09 11:29:55

标签: c# list merge

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

列表1:

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

L1结果:

enter image description here

列表2:

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

L2结果:

enter image description here


通缉结果:

enter image description here

现在,这是我合并r1和r2的方式:

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

4 个答案:

答案 0 :(得分: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);

答案 1 :(得分:0)

创建词典

Dictionary MyDict<String, List<Object>>;

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

对于每个日期,在字典中都会有一个条目,它将在此日期索引&#34;保留那段时间内发生的所有对象的列表。

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

只需确保添加数据时它不是IE IE

MyDict[Object.Period] != null

另外,Nikhil Agrawal表示我不会使用Object来保存事物列表......感觉不对并且容易出错。您可能希望声明一个将像Interface一样使用的抽象类,或者只是声明这些项(对象)的接口。

答案 2 :(得分:0)

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; 
        }
    }
}

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

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; }

    }

<强>结果 enter image description here

答案 3 :(得分:0)

我同意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();
            ;
        }
    }