亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

C# 按特定屬性比較兩個大型項目列表

C# 按特定屬性比較兩個大型項目列表

C#
繁星coding 2022-10-23 13:30:18
我有兩個大型項目列表,它們的類看起來像這樣(兩個列表都屬于同一類型):public class Items{ public string ItemID { get; set; } public int QuantitySold { get; set; }}var oldList = new List<Items>(); // oldListvar newList = new List<Items>(); // new list舊列表包含來自數據庫的項目,新列表表示從 API 獲取的項目;兩個列表都可能非常大,每個列表包含 10000 多個項目(總共 20000 個)我需要將 newList 中的項目與“oldList”中的項目進行比較,并查看哪些項目具有相同的 itemID 值,具有不同的“QuantitySold”值,而那些具有不同“QuantitySold”值的項目應存儲在名為“不同數量的項目”。我可以簡單地做雙 foreach 列表并比較值,但由于兩個列表都很大,雙 foreach 循環的性能很糟糕,我做不到......有人可以幫我解決這個問題嗎?@YamamotoTetsua 我已經在使用 IEqualityComparer 來獲得所需的結果,但是它并沒有給出我期望的結果。這就是為什么......我有一個看起來像這樣的第一個 IEqualityComparer: public class MissingItemComparer : IEqualityComparer<SearchedUserItems>    {        public static readonly IEqualityComparer<SearchedUserItems> Instance = new MissingItemComparer();        public bool Equals(SearchedUserItems x, SearchedUserItems y)        {            return x.ItemID == y.ItemID;        }        public int GetHashCode(SearchedUserItems x)        {            return x.ItemID.GetHashCode();        }    }這個 IEqualityComparer 的使用基本上給了我來自 newList 的項目,這些項目在我的數據庫中不存在,如下所示:var missingItems= newItems.Except(competitor.SearchedUserItems.ToList(), MissingItemComparer.Instance).ToList();現在在此列表中,我將列出 API 中的新項目列表,并且不存在于我的數據庫中...第二個 IEqualityComparer 基于舊列表和新列表中不同的 QuantitySold:public class ItemsComparer : IEqualityComparer<SearchedUserItems>    {        public static readonly IEqualityComparer<SearchedUserItems> Instance = new ItemsComparer();        public bool Equals(SearchedUserItems x, SearchedUserItems y)        {            return (x.QuantitySold == y.QuantitySold);        }        public int GetHashCode(SearchedUserItems x)        {            return x.ItemID.GetHashCode();        }    }使用示例:var differentQuantityItems = newItems.Except(competitor.SearchedUserItems.ToList(), ItemsComparer.Instance).ToList();他們確實從我的 oldList 中丟失了......但是第二個 IEQualityComparer 也會將這些項目作為 differentQuantity 項目返回,它們確實是,但它們不存在于 oldList 中。所以它們不應該包含在第二個列表中.
查看完整描述

4 回答

?
RISEBY

TA貢獻1856條經驗 獲得超5個贊

這是 LINQ Join的完美候選人:


var differentQuantityItems =

    (from newItem in newList

     join oldItem in oldList on newItem.ItemID equals oldItem.ItemID

     where newItem.QuantitySold != oldItem.QuantitySold

     select newItem).ToList();

這將返回所有具有不同 QuantitySold 的對應舊項目的新項目。如果您還想包含沒有相應舊項目的新項目,請使用左外連接


var differentQuantityItems =

    (from newItem in newList

     join oldItem in oldList on newItem.ItemID equals oldItem.ItemID into oldItems

     from oldItem in oldItems.DefaultIfEmpty()

     where oldItem == null || newItem.QuantitySold != oldItem.QuantitySold

     select newItem).ToList();

在這兩種情況下,連接運算符都用于快速關聯具有相同 ItemID 的項目。然后您可以比較 QuantitySold 或任何其他屬性。


查看完整回答
反對 回復 2022-10-23
?
開心每一天1111

TA貢獻1836條經驗 獲得超13個贊

即使根本沒有匹配項,此代碼也將在不到一秒的時間內運行(如果一切都匹配,也將在不到一秒的時間內運行)。


它將返回兩個列表中存在的所有項目(即相同ItemID)但具有不同的QuantitySold.


using System;

using System.Collections.Generic;

using System.Linq;


namespace ConsoleApp5

{

    class Program

    {

        public class Items

        {

            public string ItemID { get; set; }

            public int QuantitySold { get; set; }

        }


        static void Main(string[] args)

        {

            // Sample data

            var oldList = new List<Items>();

            oldList.AddRange(Enumerable.Range(0, 20000).Select(z => new Items() { ItemID = z.ToString(), QuantitySold = 4 }));


            var newList = new List<Items>();

            newList.AddRange(Enumerable.Range(0, 20000).Select(z => new Items() { ItemID = z.ToString(), QuantitySold = 5 }));


            var results = oldList.Join(newList,

                                            left => left.ItemID,

                                            right => right.ItemID,

                                            (left, right) => new { left, right })

                                .Where(z => z.left.QuantitySold != z.right.QuantitySold).Select(z => z.left);


            Console.WriteLine(results.Count());

            Console.ReadLine();

        }

    }

}

的使用z.left意味著只有一個項目將被退回 - 如果你想要舊的和新的,而不是使用:


var results = oldList.Join(newList,

                                left => left.ItemID,

                                right => right.ItemID,

                                (left, right) => new { left, right })

                    .Where(z => z.left.QuantitySold != z.right.QuantitySold)

                    .Select(z => new[] { z.left, z.right })

                    .SelectMany(z => z);


查看完整回答
反對 回復 2022-10-23
?
POPMUISE

TA貢獻1765條經驗 獲得超5個贊

從大 O 復雜性的角度來看,僅比較嵌套 for 循環中的列表將屬于O(n*m)類,其中n是數據庫中列表的大小,而m是列表的大小從 API 獲取。

為了提高性能,您可以做的是對兩個列表進行排序,這將花費O(n log (n) + m log (m)),然后您可以在O(n + m)中找到新項目。因此,您的算法的整體復雜性將屬于O(n log (n) + m log (m))類。

這是一個關于所花費時間的想法,將二次解與超線性解進行比較。


查看完整回答
反對 回復 2022-10-23
?
函數式編程

TA貢獻1807條經驗 獲得超9個贊

您可以考慮使用帶有自定義編寫的 except 子句,IEqualityComparer如下所示


var oldList = new List<Item>(); // oldList

var newList = new List<Item>(); // new list

var distinctList = newList.Except(oldList,new ItemEqualityComparer()).ToList();




class ItemEqualityComparer : IEqualityComparer<Item>

        {

            public bool Equals(Item i1, Item i2)

            {

                if (i1.ItemID == i2.ItemID && i1.QuantitySold != i2.QuantitySold)

                    return false;

                return true;

            }


            public int GetHashCode(Item item)

            {

                return item.ItemID.GetHashCode();

            }

        }


public class Item

        {

            public string ItemID { get; set; }

            public int QuantitySold { get; set; }

        }


查看完整回答
反對 回復 2022-10-23
  • 4 回答
  • 0 關注
  • 193 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號