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#/LINQ比较两个列表并赋值的最快方法_C#_Linq_List_C# 4.0_Iequalitycomparer - Fatal编程技术网

C#/LINQ比较两个列表并赋值的最快方法

C#/LINQ比较两个列表并赋值的最快方法,c#,linq,list,c#-4.0,iequalitycomparer,C#,Linq,List,C# 4.0,Iequalitycomparer,我编写了一个代码,基本上比较了C#中的两个列表。第一个列表包含如下属性: 项目ID 总体视图 第一个列表缺少TotalView的值,所以我从第二个列表中分配它们,第二个列表具有以下特性: 项目ID 命中率//这是需要分配的TotalView的属性 代码如下: foreach (var item in parsedMerchantData) { var itemInB = HitCountItemIDS.FirstOrDefault(x => x.ItemID == item

我编写了一个代码,基本上比较了C#中的两个列表。第一个列表包含如下属性:

  • 项目ID
  • 总体视图
第一个列表缺少TotalView的值,所以我从第二个列表中分配它们,第二个列表具有以下特性:

  • 项目ID
  • 命中率//这是需要分配的TotalView的属性
代码如下:

foreach (var item in parsedMerchantData)
{
    var itemInB = HitCountItemIDS.FirstOrDefault(x => x.ItemID == item.ItemID);
    if (itemInB != null)
    {
        if (itemInB.HitCount != -1)
        {
            item.TotalViews = itemInB.HitCount;
        }
        else
        {
            item.TotalViews = 0;
        }
    }
}

有没有更有效的方法使用LINQ编写此代码,或者实现一个自定义比较器,该比较器在包含100000项的较大列表上工作得更快?

代码如下所示。不确定HitCountItemID的类型。如果它是匿名的,则只需制作“var dict”:

Dictionary<string, ABC_TYPE> dict = HitCountItemID.GropupBy(x => x.ItemID, y => y).ToDictionary(x => x.Key, y => y.FirstOrDefault())
foreach (var item in parsedMerchantData)
{
    var itemInB = dict[item.ItemID];
    if (itemInB != null)
    {
        if (itemInB.HitCount != -1)
        {
            item.TotalViews = itemInB.HitCount;
        }
        else
        {
            item.TotalViews = 0;
        }
    }
}
Dictionary dict=HitCountItemID.gropubby(x=>x.ItemID,y=>y).ToDictionary(x=>x.Key,y=>y.FirstOrDefault())
foreach(parsedMerchantData中的变量项)
{
var itemInB=dict[item.ItemID];
如果(itemInB!=null)
{
如果(itemInB.HitCount!=-1)
{
item.TotalViews=itemInB.HitCount;
}
其他的
{
item.TotalViews=0;
}
}
}

我假设您在程序运行/收集数据期间持有两个列表,因此您可以在插入期间对它们进行排序。或者,如果它们在DB中,并且ID上有一个索引,那么它也可以工作

如果是这样的话,您应该能够在每个数组中只运行一次,这将非常高地优化程序(现在,根据值的不同,您得到了大约n^2的复杂性),更改后,您将得到n

int i = 0, j = 0;

while( i < parsedMerchantData.Count && j < HitCountItemIDS.Count)
{
    var item = parsedMerchantData[i];
    var itemInB = HitCountItemIDS[j];

    if (itemInB.ItemID == item.ItemID)
    {
        item.TotalViews = (itemInB.HitCount > 0) ? itemInB.HitCount : 0;
        i++;
        j++;
    }
    else if(itemInB.ItemID < item.ItemID)
        i++;
    else  //itemInB.ItemID > item.ItemID
        j++;
}
inti=0,j=0;
而(i0)?itemInB.HitCount:0;
i++;
j++;
}
else if(itemInB.ItemIDitem.ItemID
j++;
}

代码看起来应该类似于上面的代码,您应该添加更多关于何时结束的控制以及剩余值应该发生什么(这将在
i
j
到达末尾时停止)。

以下是伪代码:

var arr1 = parsedMerchantData.OrderBy(x => x.ItemID).ToArray();
var arr2 = HitCountItemID.OrderBy(x => x.ItemID).ToArray();

var i, j = 0;
while(i + j < arr1.Length() + arr2.Length()) // or similar condition
{
    if (arr1[i].ItemID < arr2[j].ItemID) {
        if (i < arr1.Length() - 1) {
            i++;
        }
        continue;
    }

    if (arr1[i].ItemID > arr2[j].ItemID) {
        if (j < arr2.Length() - 1) {
            j++;
        }
        continue;
    }

    if (arr1[i].ItemID == arr2[j].ItemID) {
        arr1[i].TotalViews = arr2[j].HitCount != -1 ? arr2[j].HitCount : 0;
    }

    // Make sure you do not let i and j grow higher then lengths of arrays
}
var arr1=parsedMerchantData.OrderBy(x=>x.ItemID.ToArray();
var arr2=HitCountItemID.OrderBy(x=>x.ItemID.ToArray();
var i,j=0;
而(i+jarr2[j].ItemID){
如果(j
其思想是应用合并排序算法。
至于复杂性,你花费O(n*log(n))对每个列表进行排序,然后O(n)遍历它们。总数是O(n*log(n)),这是我看到的最快的方式。

这类似于jdweng的答案,但稍微简单一点,它不会引发缺少项目ID的异常:

var hitCountsById = HitCountItemIDS.ToDictionary(x => x.ItemID, x => x.HitCount);
foreach (var item in parsedMerchantData)
{
    int hitCount;
    // We don't care about the return value of TryGetValue here...
    hitCountsById.TryGetValue(item.ItemID, out hitCount);
    item.HitCount = hitCount == -1 ? 0 : hitCount;
}

这应该是O(N+M),其中N是
HitCountItemIDs
的大小,
M
parsedMerchantData
的大小。。。因此,随着数据越来越大,它的增长速度应该比合并排序方法慢,而且绝对是更简单的代码。(订购时也不需要比较商品ID,只要相等即可。)

请在将来对您的问题进行格式化。你现在已经问了100多个问题——这是充分了解降价工作原理的时间。在我修改你的文章之前,你的文章格式不好是没有理由的。如果你能提供一个。有各种各样的方法来解决这个问题。。。字典是一个明显的起点,但我们不知道在
HitCountItemIDS
中是否会有两个元素具有相同的ID。我脑海中的一个优化是按ID对两个列表进行排序,并执行类似MergeSort的操作,即一次遍历两个列表。LINQ并不意味着它是最快的方式,而是写起来和可读性都很快的方式。如果你想对一个或两个列表进行排序,你可以使它的性能更好。取决于您如何保存结果以及是否对其进行了索引。Dictionary dict=HitCountItemID.gropubby(x=>x.ItemID,y=>y)。ToDictionary(x=>x.Key,y=>y.FirstOrDefault());查找将是dict[item.item]这会比人们提到的合并排序和其他方法更快吗?@User987-不会,但肯定更干净。@DmytroBogatov解析的数据是concurrentbag还是list重要吗?现在它是一种concurrentbag。。。如果我将其强制转换到列表中,我是否应该获得更快的性能?@User987-您不能仅强制转换到列表,您必须重建该结构,这会导致性能损失。我不知道LINQ的内部算法,但我觉得不行,你们不应该转换成列表。GroupBy无论如何都将遍历所有元素,而不管顺序如何。这将查找任何缺少的项目-您需要使用
TryGetValue
而不是索引器。(但我也是这样做的——它可能比合并排序方法更有效。它基本上应该是O(N+M)。考虑到条目ID是唯一的,您不需要使用
GroupBy
调用——只需
var dict=HitCountItemIDS.ToDictionary(x=>x.ItemID)