根据字典键值在列表中排序

时间:2020-01-03 11:56:10

标签: c# list linq dictionary key-value

我有以下列表:

List<Student> list = 
[
  {
    "id": 1,
    "name": "Student 1",
    "OtherInformation": {
      "hobby": "Music",
      "Score": 50
    }
  },
  {
    "id": 2,
    "name": "Student 2",
    "OtherInformation": {
      "hobby": "Golf",
      "Score": 70
    }
  },
  {
    "id": 3,
    "name": "Student 3",
    "OtherInformation": {
      "hobby": "Archery",
      "Score": 30
    }
  }
]

Other Information是一个字典,我需要OrderBy使用字典值的完整列表,该值将是动态的,即存储在某个变量中。

var sortKey = "id";
var propertyInfo = typeof(Student).GetProperty(sortKey);
list = list.OrderBy(x => propertyInfo.GetValue(x, null)).ToList();

我无法为Score之类的字典键值执行上述解决方案

Student.cs

 public class Student
{
 public string Id {get;set;}
 public string Name {get;set;}
 public IDictionary<string, object> OtherInfomration{get;set;}
}

需要帮助。

3 个答案:

答案 0 :(得分:2)

我认为您想这样做:

var sortKey = "OtherInformation";
var propertyInfo = typeof(Student).GetProperty(sortKey);
list = list.OrderBy(x => ((IDictionary<string, object>)propertyInfo.GetValue(x, null))["Score"]).ToList();

目前尚不清楚为什么要使用反射。您可以轻松地做到这一点:

list = list.OrderBy(x => x.OtherInformation["Score"]).ToList();

答案 1 :(得分:0)

我使用以下数据制作了一个迷你控制台应用程序:

 class Program
 {
     static void Main(string[] args)
     {
         List<Student> list = new List<Student>()
            {
             new Student() { Id = 1, Name = "Student 1", OtherInformation = new Dictionary<string, string>()
                                         {
                                             { "hobby", "Music" },
                                             { "Score",  "50" }
                                         }
                                     },
             new Student() { Id = 2, Name = "Student 2", OtherInformation = new Dictionary<string, string>()
                                         {
                                             { "hobby", "Golf" },
                                             { "Score",  "70" }
                                         }
                                     },
             new Student() { Id = 3, Name = "Student 3", OtherInformation = new Dictionary<string, string>()
                                         {
                                             { "hobby", "Archery" },
                                             { "Score",  "30" }
                                         }
                                     }
         };

         Console.WriteLine(list.OrderBy(x => x.OtherInformation["Score"]).FirstOrDefault().Name);
         Console.Read();
      }
 }

结果是学生3想要的,因为他的分数最低。

编辑:

您可以在此处使用预定义的订单说明:

public class OrderByStatment
{
    private string propertyName;

    public OrderByStatment(string propertyName)
    {
        this.propertyName = propertyName;
    }

    public Expression<Func<Student, object>> GetOrderBy()
    {
        switch (this.propertyName)
        {
            case "id": return s => s.Id;
            case "name": return s => s.Name;
            case "score": return s => s.OtherInformation["Score"];
            case "hobby": return s => s.OtherInformation["hobby"];
            default: return s => s.Id;
        }
    }
}

随后将进行呼叫:

Console.WriteLine(list.OrderBy(new OrderByStatment("id").GetOrderBy().Compile()).FirstOrDefault().Name);
Console.WriteLine(list.OrderBy(new OrderByStatment("score").GetOrderBy().Compile()).FirstOrDefault().Name);

您绝对可以通过定义继承来使代码更好。可以使用新的IdOrderBy()代替新的OrderByStatment(“ [propertyName]”)

希望能回答您的问题

答案 2 :(得分:0)

您可以这样做:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <NeutralLanguage>en</NeutralLanguage>
    <AssemblySearchPaths>
        $(AssemblySearchPaths);
        $(ReferencePath);
    </AssemblySearchPaths>
  </PropertyGroup>
  <ItemGroup>
    <None Remove="picture.png" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Plugin" Version="5.2.0" />
  </ItemGroup>

  <ItemGroup>
    <Reference Include="SomeLibrary">
      <HintPath>pat\to\library\netstandard2.0\SomeLibrary.dll</HintPath>
    </Reference>
  </ItemGroup>

    <ItemGroup>
        <Compile Update="Common\Localization\AppResources.Designer.cs">
            <AutoGen>True</AutoGen>
            <DesignTime>True</DesignTime>
            <DependentUpon>AppResources.resx</DependentUpon>
        </Compile>
    </ItemGroup>
    <ItemGroup>
        <EmbeddedResource Update="Common\Localization\AppResources.de.resx">
            <SubType>Designer</SubType>
        </EmbeddedResource>
        <EmbeddedResource Update="Common\Localization\AppResources.resx">
            <Generator>PublicResXFileCodeGenerator</Generator>
            <LastGenOutput>AppResources.Designer.cs</LastGenOutput>
            <SubType>Designer</SubType>
        </EmbeddedResource>
    </ItemGroup>
    <ItemGroup>
      <None Update="App.xaml">
        <Generator>MSBuild:Compile</Generator>
      </None>
      <None Update="SomePage.xaml">
        <Generator>MSBuild:Compile</Generator>
      </None>
    </ItemGroup>

</Project>

Convert.ToInt32有点狡猾,因为它可能引发异常。