Упорядочение списка по большинству вхождений наименьшего числа

#c# #sorting

#c# #сортировка

Вопрос:

Я играл с этим уже довольно давно, но не мог понять это или найти существующий вопрос об этом. Я пишу инструмент C # для подсчета очков в гонках, где мне нужно получить общий результат. Для этого результата применяются некоторые специальные правила, которые я не могу придумать, как это сделать наилучшим образом:

У меня есть список с результатами гонки (победитель получает 0 очков, 2-й получает 2, 3-й получает 3 и т. Д.). Чтобы результаты работали, мы сначала упорядочиваем по сумме всех точек. Когда это будет сделано, все еще существует вероятность того, что драйверы разделят одинаковое количество баллов. В этом случае мы должны посмотреть на их наилучшие результаты, например:

драйвер 1 набрал: 0 0 4 = 4 водитель 2 набрал очки: 2 2 0 = 4

В этом случае драйвер 1 будет первым, потому что у него больше всего выигрышей, драйвер 2 будет следовать, потому что у него только одна победа. Это должно применяться ко всем участникам.

Обновление: модель данных, которую я имею, выглядит следующим образом:

     public class SerieResultForPilot {
            public long Position { get; set; }
            public Pilot Pilot { get; set; }
            public List<SerieResultEntry> SerieResultEntries { get; set; }
            public long Total { get; set; }
        }

        public class SerieResultEntry {
            public long Points { get; set; }
            public long Penalties { get; set; }
        }
  

Порядок, который у меня есть в настоящее время, но работает неправильно:

        var orderedList = serieResultList.OrderBy(rfp => rfp.Total);
            for (int i = 0; i < pilots.Count; i  ) {
                orderedList = orderedList.ThenBy(c => c.SerieResultEntries.Count(sre => sre.Points == i));
            }
  

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

Заранее спасибо, отметьте

Решение Функция сравнения

     public class SerieResultForPilot {
            public long Position { get; set; }
            public Pilot Pilot { get; set; }
            public List<SerieResultEntry> SerieResultEntries { get; set; }
            public long Total { get; set; }

            public long CompareTo(SerieResultForPilot other) {
                var result = this.Total - other.Total;
                if (result != 0) {
                    return resu<
                }
                var thisResults = this.SerieResultEntries.OrderBy(x => x.Points).Select(x => x.Points).ToArray();
                var otherResults = other.SerieResultEntries.OrderBy(x => x.Points).Select(x => x.Points).ToArray();
                for (var i = 0; i < thisResults.Length; i  ) {
                    if (thisResults[i] != otherResults[i]) {
                        return thisResults[i] - otherResults[i];
                    }
                }
                return 0;
            }
        }

        public class SerieResultEntry {
            public long Points { get; set; }
            public long Penalties { get; set; }
        }
  

Упорядочение

     var orderedList = serieResultList.OrderBy(rfp => rfp.Total);
    foreach (var result in serieResultList) {
          orderedList = orderedList.ThenBy(c => c.CompareTo(result));
    }
  

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

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

2. Похоже, это похоже на решение проблемы программирования. Пожалуйста, опубликуйте свой код

3. Не могли бы вы также предоставить нам дополнительную информацию о вашей модели данных.

4. Как вы проводите различие между 5-кратным победителем и 5-кратным на 4-м месте?

5. Я обновил свой вопрос с использованием модели данных. @mybirthname В этом случае, я полагаю, у них не будет одинаковых очков для общего подсчета очков, поэтому 5-кратный победитель будет выше 5-кратного 4-го при первом заказе по общему количеству очков

Ответ №1:

вы можете реализовать IComparable интерфейс в построении класса вокруг результата.

в соответствии с вашей моделью данных метод сравнения может выглядеть примерно так

 public int CompareTo(SerieResultForPilot other){
    var result this.Total - other.Total;
    if (result != 0){
        return resu<
    }else{
        var thisResults = this.SerieResultEntries.OrderBy(x => x.SerieResultEntries.Points).toArray();
        var otherResults = his.SerieResultEntries.OrderBy(x => x.SerieResultEntries.Points).toArray();
        for (var i=0; i< thisResults.Count; i  ){
            if (thisResults[i] != otherResults[i]){
                return thisResults[i] - otherResults[i];
            }
        }
        return 0;
    }
}
  

документация по IComparable интерфейсу доступна здесь https://msdn.microsoft.com/pl-pl/library/system.icomparable (v = против 110).aspx

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

1. Спасибо, это было то, что мне было нужно! Как вы сказали в своем другом ответе, это действительно для landsailing, у нас отбрасывается каждые 4 гонки, но результаты уже помечены как отбрасываемые, поэтому реализовать это должно быть довольно легко. Я обновлю свой пост рабочей версией.

Ответ №2:

Возможно, не самый эффективный, но я думаю, что это сделает это:

 drivers.OrderBy(x => new { x.Sum(y => y.Points), 
    x.Sum(y => y.Points.Where(t => t.Points = 4)), x.Sum(y => y.Points.Where(t => t.Points = 3)) });
  

Предполагая, что точки являются перечислимыми, сохраненными для каждого драйвера.

Ответ №3:

Глядя на ваш код, я думаю, все, что вам нужно сделать, это заменить ThenBy на ThenByDescending . (Вы хотите, чтобы драйверы с самыми низкими оценками находились в верхней части списка.) Это также зависит от того, что максимальный результат гонки меньше, чем количество водителей — может быть, вам нужно <= , а не < в вашем for цикле?

Это не самый эффективный способ сделать это, но он довольно умный — я бы с трудом придумал что-то, что использовало бы меньше строк кода.

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

1. Это то, с чем я играл, но не дает результата, который я ищу.

Ответ №4:

Сначала вам нужно найти no. выигрышей и суммы очков каждого водителя, а затем сортировка записей на основе их очков и выигрышей, как показано в примере ниже:

 public class LinqUtil<T> where T : BaseClass
{
    public static void MyScore()
    {
        List<DriverScore> scores = new List<DriverScore>
        {
            new DriverScore {driverId="driver2",score=2 },
            new DriverScore {driverId="driver2",score=2 },
            new DriverScore {driverId="driver2",score=0 },
            new DriverScore {driverId="driver1",score=0 },
            new DriverScore {driverId="driver1",score=0 },
            new DriverScore {driverId="driver1",score=4 },
        };

        var _score = (from s in scores
                    group s by s.driverId into g
                    select new
                    {
                        driverId = g.Key,
                        Win = g.Count(x => x.score == 0),
                        Score = g.Sum(x => x.score)
                    }).OrderByDescending(x=>x.Score).ThenByDescending(x=>x.Win);
        foreach(var _s in _score)
        {
            Console.WriteLine(_s.driverId   " "   _s.Win   " "   _s.Score);
        }


    }
}