Эффективный выбор из подмножеств списка

#c# #list #performance #linq

#c# #Список #Производительность #linq

Вопрос:

Учитывая список векторов, как я могу эффективно выбрать все наибольшие значения свойства среди всех членов, которые разделяют другие значения среди разных свойств.

Например, со стандартным Vector3, как бы я выбрал Vector3s, которые имеют наибольшее значение Y относительно всех других членов с одинаковыми значениями X и Z.

Мой текущий рабочий метод заключается в переборе списка следующим образом:

 Vector3 current = Vector3.Zero;
List<Vector3> out = new List<Vector3>();
foreach(var member in MyList)
{
    current= member;
    foreach(var compare in MyList)
    {
        if(!predicate(current,compare))
            current = compare;
    }
    out.Add(largest);
}
 

Но это не кажется особенно эффективным, поскольку выполняет n квадратов сравнений, где n — длина списка.

Любые предложения по сокращению этого до более приемлемого числа, поскольку я намерен использовать это в критически важном для производительности разделе моего кода.

Для предиката с равными значениями X и Z наибольшее значение Y

Пример ввода:

 (1,1,1)
(1,2,1)
(1,4,1)
(2,3,2)
(2,5,2)
(1,4,2)
(1,2,2)
(1,1,2)
(2,5,1)
(2,4,1)
(2,9,1)
 

Ожидаемый результат:

 (1,4,1)
(2,5,2)
(1,4,2)
(2,9,1)
 

Комментарии:

1. почему вы не используете linq?

2. И, пожалуйста, можете ли вы добавить пример в качестве входных данных и что вы делаете, кроме как в качестве выходных данных

3. Я записал это без LINQ долгий путь. Я не знаю способа объединить это с LINQ, отсюда и вопрос

4. В вашем примере, что predicate ?

5. @MohamadMousheimish добавлен пример ввода и вывода

Ответ №1:

Для этого вы можете использовать LINQ:

 var result = vectors
    .GroupBy(v => Tuple.Create(v.X, v.Z))
    .Select(vg => vg.OrderByDescending(v => v.Y).First())
    .ToList();
 
  • В GroupBy качестве ключа будет использоваться кортеж X и Z .
  • Из каждой группы мы Select выбираем значение с наибольшим Y значением.

Попробуйте онлайн

Комментарии:

1. Очень приятно! Мне понравилась идея.

2. Только один вопрос по этому поводу: является ли GroupBy более эффективным за кулисами, чем то, что я настроил, выполняя сравнения n ^ 2?

3. @Azeranth пример, который вы привели в вопросе, на самом деле не возвращает тот же список, который вы «ожидаете», поэтому я не могу точно сравнить по времени.