簡體   English   中英

C#獲取使用結構的兩個列表之間的差異

[英]c# get difference between two lists that use structs

這是我的第一篇文章。 我在C#中相當陌生,並且正在嘗試使用結構類型的列表。

public struct MyStruct
{
    public string Field1;
    public string Field2;
}

List<MyStruct> BigList = new List<MyStruct> { };
List<MyStruct> SmallList = new List<MyStruct> { }; 

到目前為止,我所做的一切都使用了已知的類型(例如,字符串),但是對於上面示例中的列表,我無法使用任何具有肯定結果的函數。

目前,其想法是獲得使用該結構類型(列表)的兩個列表之間的差異。 BigList將始終具有比Small列表更多的項目,其想法是考慮到Field1,在SmalList中查找BigList中不存在的所有項目。 理想情況下,結果可以是相同類型的列表(列表)。

這可能嗎? 我已經嘗試了一些在stackoverflow中找到的示例,但是找不到許多使用結構列表的示例,而我嘗試過的示例卻無效。

一個適用於字符串列表的示例:

var Missing = BigList.Except(SmallList).ToList() 

可能是一個解決方案,但我需要查看一個字段(結構的Field1),而不僅僅是一個簡單的字符串。

對於這些類型的列表,使用.Sort或.Contains不能產生肯定的結果(專門查看結構的一個字段,例如List)。

有人能幫我嗎? 那很好啊!

提前致謝。 問候,

就像其他人所說的,在您的示例中使用struct尤其是由於您是C#的新手,可能不是真正的好主意,而是更多的錯誤。 我建議您用一個類替換您的結構。

您面臨的問題是,因為您使用的是自己定義的類型,所以比較將無法正常工作,或者至少無法正常工作。

它不會知道如何比較兩個對象,如果是類,則將驗證它是否是同一對象,如果是結構,則將進行字節對字節的比較(如果該結構不包含引用類型)或比較它包含的引用是否相同(如果結構包含引用類型)。

使一切正常工作所需要做的是重寫類中的Equals方法。 請參閱此MSDN文章以開始使用它: https : //msdn.microsoft.com/zh-cn/library/336aedhh(v=vs.100).aspx

另外,您可以為您的類型實現IEqualityComparer。 如果您無權訪問類實現,則它特別有用。 檢查此MSDN文章以執行此操作: https : //msdn.microsoft.com/zh-cn/library/bb300779(v=vs.110).aspx

有很多方法可以解決此問題。 這是一種非常有表現力的方法,可以使用Field1查找BigList元素, BigList元素沒有等效的SmallList

var bigListWithoutSmallList = 
    BigList.Where( b => !SmallList.Any( x => x.Field1 == b.Field1 ));

注意:使用classstruct與您的問題無關。

一種解決方案是實現IEquatable<MyStruct>

 class Program
    {
        static void Main(string[] args)
        {
            var smallList = new List<MyStruct>() { new MyStruct
          {
              Field1="1f",
               Field2 ="2f"
          },
          new MyStruct
          {
              Field1="2f",
               Field2 ="22f"
          }};
            var bigList = new List<MyStruct>() { new MyStruct
          {
              Field1="1f",
               Field2 ="2f"
          },
          new MyStruct
          {
              Field1="3 f",
               Field2 ="22f"
          },new MyStruct
          {
              Field1="4f",
               Field2 ="22f"
          } 
            };


              //find the difference 
            var diffList = smallList.Except(bigList);  

        }
        public struct MyStruct:IEquatable<MyStruct>
        {
            public string Field1;
            public string Field2;

            public bool Equals(MyStruct other)
            {
                if (this.Field1==other.Field1 && this.Field2==other.Field2)
                {
                    return true;   
                }
                return false;   
            }
            public override int GetHashCode()
            {
                return Field1.GetHashCode() & Field2.GetHashCode();
            }
       public override bool Equals(object obj)
        {
            return  this.Equals(obj);
        }
        }
    }

結果可能是帶有

       new MyStruct
              {
                  Field1="2f",
                   Field2 ="22f"
              }};

有一個名為MoreLINQ的開源庫,它提供了一個擴展方法,稱為IEnumerable<T> ExceptByExceptBy您的需要。

ExceptBy具有以下簽名:

public static IEnumerable<TSource> ExceptBy<TSource, TKey>(
    this IEnumerable<TSource> first, 
    IEnumerable<TSource> second, 
    Func<TSource, TKey> keySelector);

鍵選擇器是將源值映射到用於比較的鍵值的函數,但是結果仍然是TSource的序列。

在您的情況下,將這樣調用:

var Missing = BigList
    .ExceptBy(SmallList, (item => item.fieldToCompareBy)
    .ToList();

與在Where子句中使用ContainsAny相比,此方法具有相當好的性能。 它只需要立即遍歷second序列一次,然后就可以懶惰地從第first序列中獲取結果流。

如果僅在結構中覆蓋Equals,則Except將起作用。 訣竅是您需要在內部將其視為Nullable。

class Program
{
    static void Main(string[] args)
    {
        var smallList = new List<MyStruct>()
        {
            new MyStruct { Field1="1f", Field2 ="2f" },
            new MyStruct { Field1="2f", Field2 ="22f" }
        };

        var bigList = new List<MyStruct>()
        {
            new MyStruct { Field1="1f", Field2 ="2f" },
            new MyStruct { Field1="3f", Field2 ="22f" },
            new MyStruct { Field1="4f", Field2 ="22f" }
        };

        var result = bigList.Except(smallList);

        Console.ReadLine();
    }
}

public struct MyStruct
{
    public string Field1;
    public string Field2;
    public override bool Equals(object obj)
    {
        return Field1 == (obj as Nullable<MyStruct>).Value.Field1;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM