【问题标题】:How do you sort a KeyedCollection<TKey, TItem>?如何对 KeyedCollection<TKey, TItem> 进行排序?
【发布时间】:2011-06-07 13:06:11
【问题描述】:

基本上我有一个KeyedCollection&lt;string, CustomNode&gt;,我希望能够通过键(或者最好使用自定义比较器)对集合进行排序。

如果这不可能,有人可以推荐另一个类,其中键嵌入在我可以排序的值中吗?

【问题讨论】:

  • 您声明密钥(字符串)可能会更改,因此它不是硬静态密钥。如果数据没有经典键,则不要使用键值集合(即使是从值派生的键)。我只会使用 List 并使用 LINQ 进行排序。如果密钥正在更改, mycolletion[key] 就没有那么多实用程序,如果找不到密钥,则会抛出异常。此时您正在搜索动态数据,您可以使用 LINQ。

标签: c# generics sorting collections keyedcollection


【解决方案1】:

根据更多信息(请参阅上面answer 上的 cmets),要求在编辑属性后保持按元素属性排序的“集合”。

在这种情况下,您可以查看BindableLinq(还有其他类似的框架)并使用其中实现的 OrderBy 语句。

KeyedCollection<string, CustomNode> collection = /* from whereever */
collection.Items.AsBindable().OrderBy(c => c.PropertyOnCustomNode);

只要您编辑的属性引发 PropertyChanged 事件,它就会立即应用重新排序。如果您希望更改您的集合,请确保源集合实现 INotifyCollectionChanged。

【讨论】:

  • AsBindable().OrderBy() 是对当前元素进行排序,还是返回已排序元素的 IEnumberable?
  • 是的 - 它在迭代时按顺序输出元素。是的 - 我相信由于 BindableLinq 是内部编写的,您应该会发现它也在按顺序存储元素的副本(即预先计算的排序)。如果您希望项目按顺序存储(在您的根集合中),这会让您回到我原来使用 SortedDictionary 或 SortedList 的答案,或者在您的输入集合上调用排序算法( codeproject.com/KB/recipes/cssorters.aspx).
【解决方案2】:

在尝试解决类似问题时遇到了这个问题。如果它仍然相关,我可以使用此处的示例实现排序:

http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/56adc0f9-aa1b-4acf-8546-082bb01058f2/

基本上涉及对集合的底层列表进行排序。对我来说就像一个魅力。

干杯!

【讨论】:

    【解决方案3】:

    KeyCollection&lt;T&gt; 继承自实现 IEnumerableCollection&lt;T&gt;,因此您应该可以使用 IEnumerable.OrderBy()IEnumerable.OrderBy() 也有 allows you to supply a custom comparer 的重载。

    【讨论】:

    • OrderBy 返回一个新集合,但它不会对当前集合进行排序。
    【解决方案4】:

    这是基于 Dan 在回答中提供的链接: http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/56adc0f9-aa1b-4acf-8546-082bb01058f2/

       public class RequestTemplate : IComparable<RequestTemplate>
       {
          // This is the primary key for the object
          private Guid _guidNumber;
    
          // This is what a collection of these objects should be sorted by
          private string _buttonCaption = "";
    
    
          public Guid GuidNumber
          {
             get { return _guidNumber; }
             set { _guidNumber = value; }  // Setter only provided for deserialization usage
          }
    
          public string ButtonCaption
          {
             get { return _buttonCaption; }
             set { _buttonCaption = value; }
          }
    
    
          /// <summary>
          /// Method needed to allow sorting a collection of these objects.
          /// </summary>
          public int CompareTo(RequestTemplate other)
          {
             return string.Compare(this.ButtonCaption, other.ButtonCaption, 
                                   StringComparison.CurrentCultureIgnoreCase);
          }
       }
    
    
       public class RequestTemplateKeyedCollection : KeyedCollection<Guid, RequestTemplate>
       {
          /// <summary>
          /// Sort the collection by sorting the underlying collection, accessed by casting the Items 
          /// property from IList to List.
          /// </summary>
          public void Sort()
          {
             List<RequestTemplate> castList = base.Items as List<RequestTemplate>;
             if (castList != null)
                castList.Sort();  // Uses default Sort() for collection items (RequestTemplate)
          }
    
    
          /// <summary>
          /// Method needed by KeyedCollection.
          /// </summary>
          protected override Guid GetKeyForItem(RequestTemplate requestTemplate)
          {
             return requestTemplate.GuidNumber;
          }
       }
    

    尚未对其进行广泛测试,但它似乎可以正常工作。

    【讨论】:

      【解决方案5】:

      您可能会查看SortedDictionary 集合...但这会带来项目检索 O(log N) 的额外费用,而不是使用 O(1) 检索的 KeyedCollection。

      【讨论】:

      • 另一个类键嵌入到值中
      • 嗯? SortedDictionary 中用于排序的键可以从外部提供,甚至可以从元素“嵌入”——也就是说,它是在插入时指定的。
      • 但从那时起,它就与值分开了。如果我改变 Node 的值,我希望它改变 Key。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-19
      • 2011-11-09
      • 2014-04-18
      • 2016-05-17
      • 2016-11-24
      相关资源
      最近更新 更多