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();
}
}
}
答案 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
来展示一种更具可读性的不同方法。他们都工作。
请注意,您必须实施IComparable
,IEquatable<A>
,GetHashCode
,CompareTo
和Equals
。
如何实现这些内容存在更大的问题,因为在一个实例中,如果您的类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();
}
}
}