【问题标题】:Sorting a dictionary value which is a list of objects by given fields按给定字段对作为对象列表的字典值进行排序
【发布时间】:2015-06-17 10:55:32
【问题描述】:

我有一个 SortedDictionary,其值为对象列表。我想通过对象的给定属性对每个键的值(列表)进行排序。在当前情况下,我需要先按对象的姓氏对列表进行排序,然后再按名字排序。我尝试了 LINQ,但它很快就变得很糟糕,但没有产生结果。

编辑:

我有以下结构:

    public class Person
    {
        private string firstName;
        private string lastName;

        ...
    }

我需要按键排序的字典。但是,我需要先按 Person 的 lastName 对每个 List 进行排序,然后再按 firstName。

var dict = new SortedDictionary<string, List<Person>>();

我没有提供排序代码,因为我无法让它工作。这就是我寻求帮助的原因。

【问题讨论】:

  • 示例代码?作为提示:EqualityComparer 或其他东西应该可以完成这项工作
  • 请向我们展示一些代码以及没有产生您所追求的结果的代码。然后我们可以给你一些建设性的反馈,帮助你理解。
  • A SortedDictionary 按键排序,而不是按值排序。为什么不在将列表添加到字典之前对其进行排序?
  • @TimSchmelter 我知道字典是按键排序的。我主要需要它按键排序。但是,我也需要对列表中的值进行排序。我无法在添加列表之前对其进行排序,因为一切都是动态发生的,并且输入是从文件中读取的。
  • @zhulien: 列表可以包含重复项吗?如果没有,您可以使用SortedSet&lt;Person&gt;

标签: c# linq sorting dictionary


【解决方案1】:

您可以使用List.Sort,在这种情况下LINQ 不起作用,因为您无法在枚举期间修改字典(例如Add 或使用Value 属性):

foreach(var kv in yourSortedDictionary)
{
    kv.Value.Sort((p1, p2) => {
        int diff = p1.LastName.CompareTo(p2.LastName);
        if(diff != 0) return diff;
        return p1.FirstName.CompareTo(p2.FirstName);
    });
}

即使首先添加一个已经排序的列表会更好。

但正如我在评论中已经提到的,如果列表不能包含重复项,您可以使用SortedSet&lt;Person&gt; 而不是List&lt;Person&gt;。 .NET 仍然缺少允许重复但已排序的单一值集合类型。

【讨论】:

  • 集合不能在foreach块中修改,可以吗?
  • @zhulien:你说得对,我也害怕不允许,所以我测试了它。但直到我改变了Value。实际上,下一次迭代会引发异常。
  • 但是,“未处理的异常:System.InvalidOperationException:在枚举数实例化后修改了集合。”。在发布问题之前,我使用了提供的代码并尝试了该方法。另一方面,我之前没有想出的 SortedSet 解决方案,它似乎可以完成工作。谢谢!
  • @zhulien:是的,我自己也注意到了。看看修改后的版本。无论如何,这更有效,因为它不需要创建新列表。
  • 是的,Sort 方法应该是解决方案。我只是好奇是否可以使用 LINQ 相对简单地做到这一点,但事实证明并非如此。但是,我应该尝试一下 SortedSet 的建议。谢谢您的意见! :)
【解决方案2】:

通常我会创建一个新的 IEnumerable,而不是尝试更改现有的集合。 (这是 Linq 的做法):

IEnumerable<Tuple<string, List<Person>> dict = dict
 .Select(x => Tuple.Create(
    x => x.Key, 
    x => x.Value.OrderBy(x => x.LastName).ThenBy(x => x.FirstName)));

您也可以将其放入字典中,但可能不需要。您希望对其进行排序(List 就足够了)或按键访问(您不需要对其进行排序,在这种情况下使用 ToDictionary)。

你可能甚至不需要一个排序的字典作为源,当你在最后对它进行排序时(并在查询中添加另一个 OrderBy)。

【讨论】:

  • 他需要一个SortedDictionary,因为它必须按key排序,但Value中的列表也必须排序。
  • 我需要按键访问和维护排序顺序。然而,我不是使用元组的忠实粉丝。结构本身似乎有些可怕的错误。不过,感谢您的意见!
  • @stefan:是的,但是 OP 如何从 IEnumerable&lt;Tuple&lt;string, List&lt;Person&gt;&gt; 中获取 SortedDictionary?顺便说一句,x =&gt;Tuple.Create 中是多余的。
【解决方案3】:

我遇到了类似的挑战,并通过在 foreach(..) 语句中将包含对象的字典排序为运行中的值来解决它。

这是我如何做到的示例../ 给定原始场景...

public class Person
  {
    private string firstName;
    private string lastName;  
    ...
  }

...
Dictionary<string, Person> dictPersons = new Dictionary<string, Person>();
// statements to populate the dictionary with keys and a Person objects.
....
foreach(var personEntry in dictPersons.ORderBy(p => p.Value.lastName).ThenBy(p => p.Value.firstName)
  {
  ...
  // When you use the firtName or lastName properties,just refer to it as:
  Console.WriteLine("LastName: {0}  FirstName: {1}", personEntry.Value.lastName, personEntry.Value.firstName);
  ...
}

希望这对将来需要它的人有所帮助...

【讨论】:

    猜你喜欢
    • 2010-11-15
    • 2011-02-22
    • 2011-07-17
    • 2019-12-30
    • 2012-05-05
    • 1970-01-01
    • 2010-09-09
    相关资源
    最近更新 更多