对list中的对象进行排序<>通过多种标准

本文关键字:标准 排序 list 对象 | 更新日期: 2023-09-27 17:50:23

我有一个代表植物的对象列表,每个对象都有代表一系列可容忍的环境条件的成员属性。

我想重新排序这个列表,使植物对象按照适合性排序。

我想根据每个项目的温度/pH值范围的中间值与所提供的环境数据的接近程度,为列表中的每个项目给出温度/pH值适用性的排名。

然后我将平均排名并按此数字对列表进行排序。

但是,我不确定跟踪列表中每个项目的排名的最佳方法是什么。有人有什么建议吗?

对list中的对象进行排序<>通过多种标准

你可以这样做:

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的属性中创建任何你喜欢的数字,而不必实现比较器

您可以使用LINQ order扩展方法。现在,通常你可以这样写:

 mySet.OrderBy(x => x.SomeProperty)

但是,如果您希望按多个属性排序,您可以简单地创建一个方法来定义一个值:

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

然后CreateValueFor返回一个特定的值。例如,创建一些整数来定义它的适用性,这实际上是对象上一些属性的函数。

在类中公开计算适用性的方法,然后使用LINQ OrderBy扩展

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

var sorted = myList.OrderBy(item=>item.GetSuitabilityIndex());

在您的情况下,听起来您最好使用自定义比较器,您可以传递您的环境设置:

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;
    }
}

那么你可以在sort中使用它:

List<Plant> plants = new List<Plant>();
..
PlantEnvironmentSettings settings = new PlantEnvironmentSettings();
plants.Sort(new PlantComparer(settings));

您需要一个方法来计算一个项目的排名,让我们称之为GetRank,然后您可以在Sort方法中使用Comparison:

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

你也可以使用OrderBy扩展方法,它接受一个委托,返回每个项目的值:

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

计算排名的方法不一定是一个命名的方法,您可以通过简单地将GetRank(n)替换为您喜欢的任何表达式,将代码直接放在ComparisonOrderBy委托中。

您可以使用linq或lembda表达式对行星列表进行排序如果按秩排序,它会给你排序的列表。

假设您希望显示各种适合性标准,而不仅仅是有序的植物列表,我认为您需要定义一个带有额外数据的类:

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
}

并将植物映射到该类中,然后根据那里的综合得分进行排序。我猜您应该编写一个方法,接受一个Plant和您的标准,然后返回一个排名结构,例如

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()上的顺序结果,我认为这更清晰,更简单。)

难道不能简单地调用Sort方法,传入一个compare方法,该方法按照您刚才描述的方式进行计算吗?