Как я могу выбрать второе по величине значение из списка в C #? - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть список List<int> myList = new List<int>() { 10, 20, 8, 20, 9, 5, 20, 10 };, я хочу выбрать второе по величине значение, которое в данном случае 10.Я написал этот код, и он работает, но мне интересно, есть ли что-то короче и лучше.

List<int> myList = new List<int>() { 10, 20, 8, 20, 9, 5, 20, 10 };
myList = myList.Distinct().ToList();
var descendingOrder = myList.OrderByDescending(i => i);
var sec = descendingOrder.Skip(1).First();

Ответы [ 4 ]

0 голосов
/ 19 декабря 2018

Это не LINQ-ы, но O (N) и легко читается:

  public static int TheSecondMax()
  {
      List<int> myList = new List<int>() { 10, 20, 8, 20, 9, 5, 20, 10 };
      int max = int.MinValue;
      int secondMax = int.MinValue;
      foreach (var item in myList)
      {
          if (item > max)
          {
              max = item;
          }

          if (item > secondMax && item < max)
          {
              secondMax = item;
          }
      }

      return secondMax;
  }
0 голосов
/ 19 декабря 2018

Предложение Дейва выполнять все операции в одном конвейере действительно очень хорошо, так как позволяет избежать:

  1. ненужных промежуточных переменных
  2. с нетерпением создавая новые объекты коллекциина промежуточных этапах
  3. уменьшает беспорядок.
  4. более читабельно, т. е. легче увидеть, что происходит

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

var maximum = myList.Max();
var secondMaximum = myList.Where(x => x < maximum).Max();
0 голосов
/ 19 декабря 2018

Я думаю, что я бы избегал LINQ для этого и просто пошел бы по стандартной "петле над каждым элементом, если ток больше, чем max, подтолкнуть ток max ко второму месту, текущее значение к току max"

int sec = int.MinValue;
for(int i =0, m= int.MinValue; i <list.Length; i++)
  if(list[i] > m){
    sec = m;
    m = list[i];
  }

Ваша логика различает значения, поэтому похоже, что 20 не является вторым по величине в вашем списке, хотя есть три значения, равные 20. Это достигается здесь с помощью>.Если бы я использовал> =, то каждые 20 катили бы переменные, и он вел бы себя так, как если бы они не различались

Если вы заинтересованы в производительности, протестируйте его в списке с несколькими миллионами записей и выберите однучто соответствует вашему аппетиту к читабельности против скорости

0 голосов
/ 19 декабря 2018

Вы можете просто прекратить использование промежуточных переменных и ToList()

var secondHighest = 
    myList
    .Distinct()
    .OrderByDescending(i => i);
    .Skip(1)
    .First();

Это будет работать так же, как ваша версия, но требует только одного оператора вместо трех.

Мне гораздо проще читать этот список кодов.

Каждый вызов метода LINQ в отдельной строке, и никаких промежуточных переменных, особенно тех, которые изменяются (myList переназначается, чтозатрудняет понимание).

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