字典的交集<datetime,list <a =“”>&gt;

时间:2017-03-22 03:52:09

标签: c# linq

public class A
{
    public double K {get; set;}
    and other fields in here
}

我有一个由List<A>索引的Datetime词典,

Dictionary<System.Datetime, List<A>>;

如何获取所有List<A>的交集,再次作为Dictionary<System.Datetime, List<A>>返回?交点意味着最大 List<A>,使每个Datetime包含A.K

我可以用for循环来做。但我正在Linq寻找一个高性能的优雅解决方案。

{'5-19-2015', List<20, 25, 27, 30> 
 '6-10-2015', List<20, 25, 27, 28>
 '9-5-2015', List<20, 21, 22, 23, 24, 25, 26,27,28,29,30}

会返回

 {'5-19-2015', List<20, 25, 27> 
 '6-10-2015', List<20, 25, 27>
 '9-5-2015', List<20, 25, 27>}

编辑1

根据下面的建议,我试过了,但它没有工作

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestLinq
{


public class A : IComparable, IEquatable<A>
{
    public double K { get; set; }

    public int CompareTo(object obj)
    {
        A other = (A)obj;

        if (this.K > other.K)
            return 1;
        if (this.K < other.K)
            return -1;

        return 0;
    }

    public bool Equals(A other)
    {
        return this.K == other.K;
    }
}

    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<DateTime, List<A>> dict = new Dictionary<DateTime, List<A>> {
                { DateTime.Now, new List<A> {
                    new A { K = 20 }, new A { K = 25 }, new A { K = 27 }, new A { K= 30 } } },
                { DateTime.Now.AddDays(1),  new List<A> {
                    new A { K = 20 }, new A { K = 25 }, new A { K = 27 }, new A { K = 28 } } },
                { DateTime.Now.AddDays(2), new List<A> {
                    new A { K = 20 }, new A { K = 21 }, new A { K = 22 }, new A { K = 23 }, new A { K = 24 },
                    new A { K= 25 }, new A {K=  26 }, new A { K=27 }, new A {K= 28 }, new A { K=29 }, new A { K =30 } }
                }};

            var intersectedList = dict.Values.Skip(1)
                .Aggregate(
                    new HashSet<A>(dict.Values.First()),
                    (h, e) => { h.IntersectWith(e); return h; }
                );

            Console.ReadLine();
        }
    }
}

2 个答案:

答案 0 :(得分:1)

您的示例代码代表Dictionary<DateTime, List<double>>,如果是,请检查以下代码是否对您有帮助。

Dictionary<DateTime, List<double>> dict = new Dictionary<DateTime, List<double>> {
{ DateTime.Now, new List<double> { 20, 25, 27, 30 } },                
{ DateTime.Now.AddDays(1), new List<double> { 20, 25, 27, 28 } },                
{ DateTime.Now.AddDays(2), new List<double> { 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }
}};

var intersectedList = dict.Values.Skip(1)
    .Aggregate(
        new HashSet<double>(dict.Values.First()),
        (h, e) => { h.IntersectWith(e); return h; }
    );

它将返回一个20,25和27的交叉列表。

答案 1 :(得分:0)

我给予Karthik信用的信用,但是为了帮助下一个人,这是我需要做的。首先,请注意我添加了Name property,以便在我调试时,我可以告诉我正在查看哪个A。我还添加了IntersectAll来展示一种更具可读性的不同方法。他们都工作。

请注意,您必须实施IComparableIEquatable<A>GetHashCodeCompareToEquals

如何实现这些内容存在更大的问题,因为在一个实例中,如果您的类A更复杂(具有更多属性)并且对于两个对象相等的含义有不同的需求可以相互矛盾。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestLinq
{
    public class A : IComparable, IEquatable<A>
    {
        public string Name { get; set; }
        public double K { get; set; }

        public override int GetHashCode()
        {
            return K.GetHashCode();
        }

        public int CompareTo(object obj)
        {
            A other = (A)obj;

            if (this.K > other.K)
                return 1;
            if (this.K < other.K)
                return -1;

            return 0;
        }

        public bool Equals(A other)
        {
            return this.K == other.K;
        }
    }

    class Program
    {
        static public List<T> IntersectAll<T>(IEnumerable<IEnumerable<T>> lists)
        {
            HashSet<T> hashSet = new HashSet<T>(lists.First());
            foreach (var list in lists.Skip(1))
            {
                hashSet.IntersectWith(list);
            }

            return hashSet.ToList();
        }

        static void Main(string[] args)
        {
            Dictionary<DateTime, List<A>> dict = new Dictionary<DateTime, List<A>> {
                { DateTime.Now, new List<A> {
                    new A { Name = "1", K = 20 }, new A {  Name = "1", K = 25 }, new A { Name = "1", K = 27 }, new A {  Name = "1", K= 30 } } },
                { DateTime.Now.AddDays(1),  new List<A> {
                    new A {  Name = "2",K = 20 }, new A { Name = "2", K = 25 }, new A { Name = "2", K = 27 }, new A { Name = "2", K = 28 } } },
                { DateTime.Now.AddDays(2), new List<A> {
                    new A { Name = "3", K = 20 }, new A {  Name = "3",K = 21 }, new A { Name = "3", K = 22 },
                    new A { Name = "3", K = 23 }, new A {  Name = "3",K = 24 },
                    new A { Name = "3", K= 25 }, new A { Name = "3",K=  26 }, new A {  Name = "3",K=27 },
                    new A { Name = "3", K= 28 }, new A { Name = "3", K=29 }, new A { Name = "3", K =30 } }
                }};

#if true
            var intersectedList = dict.Values.Skip(1)
                .Aggregate(
                    new HashSet<A>(dict.Values.First()),
                    (h, e) => { h.IntersectWith(e); return h; }
                );
#else
            var intersectList = IntersectAll( dict.Values);
#endif
            Console.ReadLine();
        }
    }
}