Dot-Net

如何使用 linq 按自定義類型分組

  • February 9, 2022

我有這門課

public class Item
{
      public Coordinate coordinate { get; set; }
       ...
       ...
}

座標定義如下:

public class Coordinate
{
       public Coordinate(float latitude, float longitude)
       {
           Latitude = latitude;
           Longitude = longitude;
       }

       public float Latitude { get; private set; }
       public float Longitude { get; private set; }
}

我想要一個這樣的 linq 查詢:

var grouped = from it in items
             group it by it.Coordinate into grp
             select grp;

正如 MSDN 在這裡提到的,我認為如果我在我的 Coordinate 類上覆蓋 Equals ,這是可能的:

如果必須將查詢變數傳遞給另一個方法,請使用命名類型。使用鍵的自動實現屬性創建一個特殊類,然後覆蓋 Equals 和 GetHashCode 方法。您還可以使用結構,在這種情況下,您不必嚴格重寫這些方法。有關更多資訊,請參閱如何:實現具有自動實現屬性的不可變類

等於 Coordinate 類的實現:

public override bool Equals(object obj)
{
      var coord = obj as Coordinate;
      if(coord == null) return false;
      return (Latitude == coord.Latitude && Longitude == coord.Longitude);
}

我仍然無法讓我的 linq 查詢按相似的座標進行分組,因為我的失敗測試表明:

[TestMethod]
public void GroupBy_3ItemsWith2DifferentCoordinates_Returns2Groups()
{
   var items = new List<Item>
       {
           new Item {Coordinate = new Coordinate(10, 10)},
           new Item {Coordinate = new Coordinate(10, 10)},
           new Item {Coordinate = new Coordinate(12, 10)},
       };
   var grouped = from it in items
                 group it by it.Coordinate into g
                 select g;
   Assert.AreEqual(2, grouped.Count());
}

將 IEqualityComparer 作為參數的 GrouBy 方法有一個重載,但是否有使用 group 子句的等價物?難道我做錯了什麼??有什麼想法嗎?

您已經展示了 Equals 實現,但沒有展示 GetHashCode。您需要覆蓋兩者(並以一致的方式)才能進行分組。

範例 GetHashCode 實現:

public override int GetHashCode()
{
   int hash = 23;
   hash = hash * 31 + Latitude.GetHashCode();
   hash = hash * 31 + Longitude.GetHashCode();
   return hash;
}

請注意,比較float精確相等的值總是有些冒險 - 但我至少希望您的單元測試能夠通過,因為它們沒有執行任何計算。

引用自:https://stackoverflow.com/questions/2280183