Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 根据条件将行从一个IEnumerable添加到另一个IEnumerable_C#_Linq_C# 4.0 - Fatal编程技术网

C# 根据条件将行从一个IEnumerable添加到另一个IEnumerable

C# 根据条件将行从一个IEnumerable添加到另一个IEnumerable,c#,linq,c#-4.0,C#,Linq,C# 4.0,我有两个数组 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 = "

我有两个数组

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 }
    };
我想做的是检查
data2
中的每个不同的
产品
年份
,如果
data1
中的
产品
年份
的任何组合存在任何行,但不在
data2
中,则将该行添加到
data2

例如。。 在
data2
中,不同的产品是
Product1
Product2
,不同的年份是
Year1
Year2
Year3
Year4

在数据1中存在一行
{Product=“Product 2”,Year=2009,Sales=522}
,该行在
data2
中不存在,因此我希望将其添加到
data2

我能做的是在两个变量中得到不同的产品和年份

然后对这两个循环中的每个循环执行一次检查,检查组合是否存在于data1中,但不存在于data2中,如果存在,则将其添加到data2中

我希望得到的是一个LINQ查询,它可以为我完成这项工作,而不是分别执行两个不同的查询,然后为每个循环执行两个查询


谢谢

您可以在一个查询中实现这一点。然而,它将是次优的,因为对于
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();
var uniqueProd=newhashset(data2.Select(d=>d.Product));
var uniqueYear=newhashset(data2.Select(d=>d.Year));
var knownPairs=新哈希集(
data2.Select(d=>Tuple.Create(d.Product,d.Year))
);
var newData2=data2.Concat(
数据1.其中(d=>
uniqueProd.Contains(d.Product)//产品在那里
&&uniqueYear.Contains(d.Year)//年份在那里
&&!knownPairs.Contains(Tuple.Create(d.Product,d.Year))//组合不存在
)
).ToArray();

这个解决方案在时间上是O(m+n),在空间上也是O(n)。

我不会对效率提出任何要求,但它可以在单个查询中实现

如果您满足于让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);
或者,您可以排除预先存在的数据2匹配,并使用
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
    );
奥托,我忍不住要计时。如果我们将使用Union作为1调用,使用Concat的时间占73%,创建哈希集的时间占827%,提取唯一的对集的时间占54%,跳过.Distinct()的时间占27%,尽管数据集的速度太慢,无法分辨其中的一些差异

拔出配对并卸下:

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

您的意思是直接将其添加到另一个数组中,还是只需要一个包含
data2
中的项和
data1
中的某些项的新集合?后者更容易,因为数组的大小是固定的。我同意后者,事实上后者更好。而且
{Product=“Product 1”,Year=2009,Sales=1212}
存在于两个数组中,所以我不明白为什么你说它需要添加到
Data2
对不起,我的意思是{Product=“Product 2”,Year=2009,Sales=522},同时编辑问题您应该将
Union
与自定义相等比较器一起使用,但由于您使用的是匿名类型,相等比较器有点不同。因此,我认为最好是搜索实现匿名类型的
IEqualityComparer
。+1用于使用HashSet。我正在努力理解HashSet。你能评论一下你方和我方的不同之处吗?谢谢@赢取您的解决方案将包括来自
data1
的年份/产品组合,即使是
data2
中不存在的配对。具体来说,我认为OP不希望最后一行出现
Product3
,因为
Product3
不在
data2
的产品中。在此之前,我从未见过Hashset的使用。它比列表快吗。如果您能看看我的一个老问题()并告诉我Hashset的用法是否对第二次和第三次查询特别有用,我将不胜感激。您能告诉我您是如何获得计时信息的吗。。我希望在我的数据集上使用相同的方法。我使用LinqPad和内置的Util.ElapsedTime来计算不同查询的计时。通常,您可以使用StopWatch类为部分代码计时,或者使用VisualStudio评测。