【问题标题】:Two dictionaries intersection C# [duplicate]两个字典交集C# [重复]
【发布时间】:2018-06-11 17:39:07
【问题描述】:

我有两个 DateTime 列表,并且可以毫无问题地将它们相交:

IEnumerable<DateTime> both = list1.Intersect(list2);

我有自定义数据类型,仍然需要找到交集:

public class AssetRecord
{
    // Custom data type. Each object has time and price
    public DateTime AssetDate { get; set; } 
    public double AssetPrice { get; set; }
}

// Lits initialization
public static List<AssetRecord> list1 = new List<AssetRecord> { }; 
// Key/Values - Date/Price. Custom data type is used to store an object in the collection
public static List<AssetRecord> list2 = new List<AssetRecord> { }; 

问题在于 IEnumerable 仅将 DataTime 列表作为输入,而我不再拥有该数据类型。是否可以使用自定义类型找到交集?或者是否可以仅从创建的数据类型中获取 Date 字段并将其转换为 List 然后将其传递给 IEnumerable?

【问题讨论】:

  • 重写assetrecord函数的equals方法来检查里面的两个字段是否匹配...应该可以工作
  • 你需要为你的类型定义相等性(docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…),或者在Enumerable.Intersect的重载中使用自定义IEqualityComparer&lt;AssetRecord&gt;,它需要两个参数(msdn.microsoft.com/en-us/library/bb355408(v=vs.110).aspx)。
  • ... 或实现 IEqualityComparer 并使用 Intersect 的重载
  • @DiegoSlinger 阅读文档。它有据可查,网络上有无数示例
  • Intersect 在您使用的重载中调用 Equals 本身,您只需要实现它。如果你不想想在你的类型上定义相等,你需要实现一个IEqualityComparer并将它的一个实例传递给Intersect

标签: c#


【解决方案1】:

问题是 IEnumerable 只需要 DataTime 列表

嗯?这是没有意义的。 IEnumerable&lt;T&gt; 接受您选择的任何 T。在这种情况下,IEnumerable&lt;AssetRecord&gt; 将包含 AssetRecords。

现在,这不是您的主要问题。您的问题是 intersect 的工作方式。 Enumerable.Intersect&lt;T&gt; 采用默认相等 T。那么,AssetRecord 的默认相等比较器是什么?引用相等,您可能需要值相等语义。

解决方案?相应地在 AssetRecord 中覆盖 Equals 并同时实现 IEquatable&lt;AssetRecord&gt;(并且不要忘记以一致的行为覆盖 GetHashCode):

public class AssetRecord: //IEquatable<AssetRecord> left as exercise
{   
    // Custom data type. Each object has time and price
    public DateTime AssetDate { get; set; } 
    public decimal AssetPrice { get; set; }

    public override bool Equals(object other)
    {
         if (other is AssetRecord)
         {
             var ass = (AssetRecord)other;
             return ass.AssetDate == AssetDate &&
                    ass.AssetPrice == AssetPrice;  
         }

         return false;
    }              

    public override int GetHashCode()
    {
        return AssetDate.GetHashCode() ^ AssetPrice.GetHashCode();
    }
}

如果您无法触摸AssetRecord,则实现IEqualityComparer&lt;AssetRecord&gt; 并使用Intersect 的相应重载。

您的代码还有两个值得一提的问题:

  1. 价格应该是decimal,而不是double。您想要精确十进制值,请使用框架提供的正确工具。
  2. 您的类型已经命名为AssetRecord,它可能应该命名为Asset,但无论如何,没有必要拥有带有冗余信息的属性。 PriceDate 应该足够了。

【讨论】:

  • ass 在您的上下文中是什么意思? => 是什么意思?我在文档中没有看到它:docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…@InBetween
  • @DiegoSlinger C# 6-7 语法。
  • 我不明白。我在编程方面还没有那么先进
  • @DiegoSlinger 将语法更改为更传统的 c#。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-19
  • 2019-02-20
  • 1970-01-01
  • 2013-09-04
  • 1970-01-01
  • 2013-12-07
相关资源
最近更新 更多