如何有效地比较两个对象并计算相等属性的数量?

时间:2018-11-03 12:06:34

标签: c# list

我正在处理两个包含许多属性的列表。我试图遍历列表并以count(int)的形式返回两个对象的比较。计数定义为相等的属性数。

下面是一个示例:

    class Object{
     public string prop1 {get;set;} //x5  Avg Length (20-30 Char)
     public double prop2 {get;set;} //x3

    }
    private int CompareProps(Object a, Object b)
    {
        int matchedElements = 0;
        if (a.Prop1 == b.Pro1)
            matchedElements++; ;
        if (a.Prop2 == b.Prop2)
            matchedElements++;

        // More Property Comparisons...

        return matchedElements;
    }
    ///Loops in another method with two Lists of Object, where each list.count = 300
        List1 = getList1Objects();//300 Objects
        List2 = getList2Objects();//300 Objects
        int l1 = List1.Count;
        int l2 = List2.Count;

        Parallel.For(0, l1, i =>
        {
            for (int j = 0; j < l2; j++)
            {
                int k =  CompareProps(List1[i], List2[j]);
            }
        });

这是非常低效的。在C#中有更好的方法吗?这些属性可以是字符串,双打等。

谢谢!

3 个答案:

答案 0 :(得分:2)

如果性能真的很重要,我认为您需要Intersect,因为它使用HashSets。

private static int CompareProps(MyObject a, MyObject b)
{
     var aValues = a.GetType().GetProperties().Select(x => x.GetValue(a, null));
     var bValues = b.GetType().GetProperties().Select(x => x.GetValue(b, null));

     return aValues.Intersect(bValues).Count();
}

这是示例用法。

var a = new MyObject
{
   prop1 = "abc", // same value
   prop2 = "def",
   prop3 = 123,
   prop4 = 456 // same value
};

var b = new MyObject
{
   prop1 = "abc", // same value
   prop2 = "jkl",
   prop3 = 789,
   prop4 = 456 // same value
};

Console.WriteLine(CompareProps(a, b)); // output 2

编辑:

通过运行300X300列表循环测试了我的解决方案。

private static void Run()
{
  var alist = new List<MyObject>();
  for (var i = 0; i < 300; i++)
  {
    alist.Add(new MyObject
    {
        prop1 = "abc",
        prop2 = RandomString(),
        prop3 = random.Next(),
        prop4 = 123
    });
  }

  var blist = new List<MyObject>();
  for (var i = 0; i < 300; i++)
  {
     blist.Add(new MyObject
     {
        prop1 = "abc",
        prop2 = RandomString(),
        prop3 = random.Next(),
        prop4 = 123
     });
  }

  var watch = new Stopwatch();
  watch.Start();

  Parallel.For(0, alist.Count, i =>
  {
     for (var j = 0; j < blist.Count; j++)
     {
        Console.WriteLine("Result: " + CompareProps(alist[i], blist[j]));
     }
  });

  Console.WriteLine(watch.Elapsed.TotalSeconds + "  seconds..");
}
  

结果:9.1703053秒。.

enter image description here

答案 1 :(得分:0)

您可以像这样比较它们:

private int CompareProps(Object a, Object b)
{
    int matchedElements = 0;
    var props = a.GetType().GetProperties();
    foreach(var prop in props)
    {
        var vala = prop.GetValue(a);
        var valb = prop.GetValue(b);
        if(vala == valb)
            matchedElements++;

    // More Property Comparisons...
    return matchedElements;
}

为类属性的将来更改编写和维护更容易。但是请注意,这肯定会花费更多时间。因此,您打算比较不建议使用此方法的对象的数百个实例。

答案 2 :(得分:0)

如果两个列表中都可能出现相同的对象,则可以通过引用或哈希将ab进行比较,以进行快速短路。

如果内部列表创建缓慢(例如,从数据库查询),则可以在大小/内存允许的情况下在循环外拍摄快照.ToList()

就是这样。有时候,工作就是工作。