我有两个阵列..
var data1 = new[] {
new { Product = "Product 1", Year = 2009, Sales = 1212 },
new { Product = "Product 2", Year = 2009, Sales = 522 },
new { Product = "Product 1", Year = 2010, Sales = 1337 },
new { Product = "Product 2", Year = 2011, Sales = 711 },
new { Product = "Product 2", Year = 2012, Sales = 2245 },
new { Product = "Product 3", Year = 2012, Sales = 1000 }
};
var data2 = new[] {
new { Product = "Product 1", Year = 2009, Sales = 1212 },
new { Product = "Product 1", Year = 2010, Sales = 1337 },
new { Product = "Product 2", Year = 2011, Sales = 711 },
new { Product = "Product 2", Year = 2012, Sales = 2245 }
};
我想要做的是检查Product
中的每个不同Year
和data2
,以及Product
和{{1}的任何组合是否存在任何行在Year
但不在data1
中,然后将该行添加到data2
。
实施例..
在data2
中,不同的产品是data2
和Product1
,不同的年份是Product2
,Year1
,Year2
和Year3
。< / p>
在data1中存在行Year4
,{ Product = "Product 2", Year = 2009, Sales = 522 }
中不存在,因此我希望将其添加到data2
。
我能做的是获得两个变量的不同产品和年份。
然后为两个循环执行a并检查data1中是否存在组合,但是不存在于data2中,如果存在,则将其添加到data2。
我想得到的是单个LINQ查询,它可以为我完成这项工作,而不是分别做两个不同的事情,然后为每个循环做几个。
由于
答案 0 :(得分:2)
您可以在单个查询中使用此功能。然而,它将是次优的,因为对于data1
中的每个项目,您需要检查三个条件,这可能需要遍历整个data2
以获得O(m * n)时间复杂度(空间复杂性仍然是O(1))。
你可以避免使用相同的循环:
var uniqueProd = new HashSet<string>(data2.Select(d=>d.Product));
var uniqueYear = new HashSet<int>(data2.Select(d=>d.Year));
var knownPairs = new HashSet<Tuple<string,int>>(
data2.Select(d=>Tuple.Create(d.Product, d.Year))
);
var newData2 = data2.Concat(
data1.Where(d =>
uniqueProd.Contains(d.Product) // The product is there
&& uniqueYear.Contains(d.Year) // The year is there
&& !knownPairs.Contains(Tuple.Create(d.Product, d.Year)) // Combination is not there
)
).ToArray();
该解决方案的时间为O(m + n),空间也为O(n)。
答案 1 :(得分:1)
我不会对效率提出任何要求,但可以在一次查询中提出。
如果您满意让Union处理删除重复项,您可以这样做:
var newd2 = data2.Union(
from d1 in data1
where
(from d2p in data2 from d2y in data2
select new { d2p.Product, d2y.Year })
.Distinct().Any(mp => mp.Product == d1.Product && mp.Year == d1.Year)
select d1);
或者,您可以排除预先存在的data2匹配并使用Concat
var newd2 = data2.Concat(
from d1 in data1
where
(from d2p in data2 from d2y in data2 select new { d2p.Product, d2y.Year })
.Distinct().Any(mp => mp.Product == d1.Product && mp.Year == d1.Year) &&
!data2.Any(mp => mp.Product == d1.Product && mp.Year == d1.Year)
select d1
);
OTOH,我无法抗拒某些时间。如果我们使用Union作为1调用,使用Concat的时间从73%开始不同,创建HashSets使用827%的时间并且拉出唯一对的设置需要54%,跳过.Distinct()需要27%,尽管数据集太慢,无法区分其中的一些。
拉出对并倾倒Distinct:
var newdd = (from d2p in data2 from d2y in data2 select new { d2p.Product, d2y.Year });
var newd2 = data2.Concat(
from d1 in data1
where
newdd.Any(mp => mp.Product == d1.Product && mp.Year == d1.Year) &&
!data2.Any(mp => mp.Product == d1.Product && mp.Year == d1.Year)
select d1
);