Как эффективно сравнить два объекта и посчитать количество равных свойств? - PullRequest
0 голосов
/ 03 ноября 2018

Я работаю с двумя списками, которые содержат много свойств. Я пытаюсь перебрать списки и вернуть сравнение двух объектов в виде счетчика (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 голосов
/ 03 ноября 2018

Вы можете сравнить a с b либо по ссылке, либо по хешу для быстрого короткого замыкания, если есть вероятность того, что один и тот же объект встречается в обоих списках.

Если внутренний список создается медленно (например, запрос из БД), вы можете сделать снимок .ToList() вне цикла, если позволяет размер / память.

Вот и все. Хотя иногда работа есть работа.

0 голосов
/ 03 ноября 2018

Если производительность действительно важна, я думаю, вам нужно Пересечь , поскольку она использует 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

EDIT:

Протестировал мое решение, запустив цикл списка 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

0 голосов
/ 03 ноября 2018

Вы можете сравнить их так:

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;
}

Проще писать и поддерживать для будущих изменений свойств класса. Но будьте осторожны, это определенно займет больше времени. Поэтому, если вы собираетесь сравнивать сотни экземпляров объектов, этот метод не рекомендуется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...