#c# #list #ranking
#c# #Список #Рейтинг
Вопрос:
У меня есть список объектов, представляющих растения, у каждого из которых есть свойства-члены, которые представляют диапазон допустимых условий окружающей среды.
Я хочу изменить порядок этого списка таким образом, чтобы объекты plant были ранжированы в порядке их пригодности.
Я полагаю, что хочу присвоить каждому элементу в списке ранг по пригодности для температуры / pH на основе близости середины их диапазона температуры / pH к предоставленным данным об окружающей среде.
Затем я бы усреднил ранги и отсортировал список по этому номеру.
Однако я не уверен, каким был бы наилучший подход для отслеживания рангов, присвоенных каждому элементу в списке. Есть ли у кого-нибудь какие-либо рекомендации о том, как лучше всего подойти к этому?
Ответ №1:
Вы могли бы сделать это следующим образом:
var plants = new Plant[] { new Plant { T = 1, Ph = 2 }, new Plant { T = 2, Ph = 2 } };
var ps = from p in plants
let magicNumber = p.T/p.Ph // Or some other algorithm
orderby magicNumber
select p;
Тогда вы можете просто создать любое число, которое вам нравится, из свойств Plant
и вам не нужно внедрять средство сравнения.
Ответ №2:
Вы можете использовать метод расширения LINQ OrderBy. Теперь, как правило, вы могли бы написать это следующим образом:
mySet.OrderBy(x => x.SomeProperty)
Однако, если вы хотите упорядочить объекты по нескольким свойствам, вы можете просто создать метод для определения значения:
mySet.OrderBy(x => CreateValueFor(x))
А затем CreateValueFor
возвращает определенное значение. Например, создание некоторого целого числа, которое определяет его пригодность, что на самом деле является функцией некоторых свойств вашего объекта.
Ответ №3:
Предоставьте метод для вычисления пригодности в вашем классе, затем используйте расширение LINQ OrderBy
public int GetSuitabilityIndex()
{
//Calculate suitability..
}
var sorted = myList.OrderBy(item=>item.GetSuitabilityIndex());
Ответ №4:
В вашем случае, похоже, вам лучше всего использовать пользовательский компаратор, которому вы можете передавать настройки своей среды:
class PlantComparer : IComparer<Plant>
{
public PlantComparer(PlantEnvironmentSettings settings)
{
}
public int Compare(Plant plant1, Plant plant2)
{
//compare two plants, return 0, 1 or -1
return 0;
}
}
Затем вы можете использовать это для сортировки:
List<Plant> plants = new List<Plant>();
..
PlantEnvironmentSettings settings = new PlantEnvironmentSettings();
plants.Sort(new PlantComparer(settings));
Ответ №5:
Вам нужен метод для вычисления ранга элемента, давайте назовем его GetRank
, затем вы можете использовать его в Sort
методе с Comparison
:
plants.Sort((x,y) => GetRank(x).CompareTo(GetRank(y)));
Вы также можете использовать OrderBy
метод расширения, который принимает делегат, возвращающий значение для каждого элемента:
plants = plants.OrderBy(x => GetRank(x)).ToList();
Метод для вычисления ранга не обязательно должен быть именованным методом, вы можете поместить код непосредственно в делегат Comparison
или OrderBy
, просто заменив GetRank(n)
любым выражением, которое вам нравится.
Ответ №6:
вы можете отсортировать свой список планет, используя выражение linq или lembda с порядком по рангу, это даст вам отсортированный список.
Ответ №7:
Предполагая, что вы хотите отобразить различные критерии пригодности, а не просто упорядоченный список растений, я думаю, вам нужно будет определить класс с дополнительными данными:
class PlantRankings
{
public Plant Plant { get; set; }
public double PhSuitabilityScore { get; set; }
public double SoilTypeScore { get; set; }
public double SmellsNiceScore { get; set; }
public double RankingScore { get; set; } // could compute on-the-fly here
}
и сопоставьте ваши растения с этим классом, а затем отсортируйте по их суммарному баллу. Я думаю, вы бы написали метод, который принимает завод, а ваши критерии затем возвращают структуру ранжирования, например
var rankedPlants = plants.Select(p => ScoreSuitability(p, criteria))
.OrderBy(pr => pr.RankingScore).ToList();
Если под рангом вы имели в виду ранжирование 1-N для каждого объекта по каждому критерию, то опять же, я думаю, вам нужно будет сгенерировать расширенную структуру, но с
public int PhSuitabilityRank { get; set; }
наряду с оценками; затем, как только вы вычислили оценку и построили список, вы можете
int rank = 1;
for(var rankedPlant in
rankedPlants.OrderByDescending(pr => pr.PhSuitabilityScore))
{
rankedPlant.PhSuitabilityRank = rank;
rank;
}
и так далее. (Возможно, есть способ сделать это в LINQ, но без .ForEach() по результатам упорядочивания я думаю, что это понятнее и проще.)
Ответ №8:
Разве вы не можете просто вызвать метод сортировки, передав метод сравнения, который вычисляет точно так, как вы только что описали?