Ранжирование объектов в Списке <> по нескольким критериям - PullRequest
2 голосов
/ 18 апреля 2011

У меня есть список объектов, представляющих растения, каждый из которых имеет свойства-члены, представляющие диапазон допустимых условий окружающей среды.

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

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

Я бы тогда усреднил ранги и отсортировал список по этому номеру.

Тем не менее, я не уверен, каков будет лучший подход для отслеживания рангов, присвоенных каждому элементу в списке. Кто-нибудь есть какие-либо рекомендации о том, как лучше всего подойти к этому?

Ответы [ 8 ]

2 голосов
/ 18 апреля 2011

Вы можете сделать это так:

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, и вам не нужно реализовывать Comparer.

0 голосов
/ 18 апреля 2011

вы можете отсортировать список планет используя выражения linq или lembda с порядком по рангу он получит отсортированный список.

0 голосов
/ 18 апреля 2011

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

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 () для результатов Order, я думаю, это будет яснее и проще.)

0 голосов
/ 18 апреля 2011

Вам нужен метод для вычисления ранга предмета, назовем его GetRank, затем вы можете использовать его в методе Sort с Comparison:

plants.Sort((x,y) => GetRank(x).CompareTo(GetRank(y)));

Вы также можете использовать метод расширения OrderBy, который принимает делегата, который возвращает значение для каждого элемента:

plants = plants.OrderBy(x => GetRank(x)).ToList();

Метод вычисления ранга не обязательно должен быть именованным, вы можете поместить код непосредственно в делегат Comparison или OrderBy, просто заменив GetRank(n) любым выражением, которое вам нравится.

0 голосов
/ 18 апреля 2011

В вашем случае это звучит так, как будто вам лучше использовать специальный компаратор, который может передавать настройки среды:

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));
0 голосов
/ 18 апреля 2011

Укажите метод расчета пригодности в вашем классе, затем используйте расширение LINQ OrderBy

public int GetSuitabilityIndex()
{
     //Calculate suitability..
}


var sorted = myList.OrderBy(item=>item.GetSuitabilityIndex());
0 голосов
/ 18 апреля 2011

Вы можете использовать метод расширения LINQ OrderBy. Теперь, как правило, вы можете написать это так:

 mySet.OrderBy(x => x.SomeProperty)

Однако, если вы хотите упорядочить по нескольким свойствам, вы можете просто создать метод для определения значения:

mySet.OrderBy(x => CreateValueFor(x))

И тогда CreateValueFor возвращает обратно определенное значение. Например, создание целого числа, определяющего его пригодность, которое на самом деле является функцией некоторых свойств вашего объекта.

0 голосов
/ 18 апреля 2011

Разве вы не можете просто вызвать метод Sort, передав метод сравнения, который оценивается точно так, как вы только что описали?

...