C# 在列表中对对象进行排序<&燃气轮机;根据多种标准

C# 在列表中对对象进行排序<&燃气轮机;根据多种标准,c#,list,ranking,C#,List,Ranking,我有一个代表植物的对象列表,每个对象都有代表一系列可容忍环境条件的成员属性 我想重新排列此列表,以便按照适用性顺序排列植物对象 我想根据温度/pH范围的中间位置与提供的环境数据的接近程度,给列表中的每个项目一个温度/pH适合性等级 然后,我将平均排名,并根据这个数字对列表进行排序 但是,我不确定跟踪列表中每个项目的排名的最佳方法是什么。有人对如何最好地实现这一点有什么建议吗?您不能简单地调用Sort方法,传入一个比较方法,该方法的计算方式与您刚才描述的完全相同吗?您可以使用LINQ OrderB

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

我想重新排列此列表,以便按照适用性顺序排列植物对象

我想根据温度/pH范围的中间位置与提供的环境数据的接近程度,给列表中的每个项目一个温度/pH适合性等级

然后,我将平均排名,并根据这个数字对列表进行排序


但是,我不确定跟踪列表中每个项目的排名的最佳方法是什么。有人对如何最好地实现这一点有什么建议吗?

您不能简单地调用Sort方法,传入一个比较方法,该方法的计算方式与您刚才描述的完全相同吗?

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

 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;
    }
}
类PlantComparer:IComparer
{
公共PlantComparier(PlantEnvironment设置)
{
}
公共int比较(工厂1、工厂2)
{
//比较两种植物,返回0、1或-1
返回0;
}
}
然后您可以将其用于排序:

List<Plant> plants = new List<Plant>();
..
PlantEnvironmentSettings settings = new PlantEnvironmentSettings();
plants.Sort(new PlantComparer(settings));
List plants=new List();
..
PlantEnvironmentSettings=新建PlantEnvironmentSettings();
植物。排序(新植物比较器(设置));

您可以这样做:

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;

然后,您可以根据
工厂的属性创建任何您喜欢的数字,而不必实现比较器。

您需要一种方法来计算项目的排名,我们称之为
GetRank
,然后您可以在
排序
方法中使用该方法进行
比较

plants.Sort((x,y) => GetRank(x).CompareTo(GetRank(y)));
您还可以使用
OrderBy
扩展方法,该方法接受一个委托,该委托返回每个项目的值:

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

计算秩的方法不必是命名的方法,您可以通过简单地替换
GetRank(n)将代码直接放入
Comparison
OrderBy
委托中
使用您喜欢的任何表达式。

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

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(),我认为这样更清晰、更简单。)

您可以使用LINQ或lembda表达式对行星列表进行排序 通过按等级排序,它将为您提供排序列表