实现允许多个值的排序的集合/词典的最佳方法是什么? [英] What's the best way to implement a sorted collection/dictionary with multiple values allowed?

查看:129
本文介绍了实现允许多个值的排序的集合/词典的最佳方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个可以收集以下内容的对象:

*允许通过键(如在字典中)获取,设置功能对象
*我需要按照优先级"值的排序方式对集合进行遍历
*优先级允许多个值.
*键可以是整数或字符串,没关系


例如:

I need a collection of objects that will:

* allow get, set functionality object via a key (like in a dictionary)
* I need to iterate through the collection in a sorted manner, ordered by a "Priority" value
* the priority allows multiple values.
* the keys can be an int or a string, it doesn''t matter


E.g.:

key    order object
------ ----- ------
012395 0     obj8
892619 2     obj12
158276 2     obj3        
198756 2     obj5
787362 8     obj7
298656 9     obj4



什么是最好的收藏夹?
还是我必须自己强加一些东西...

Tnx,
H



What''s the best collection(s) to use?
Or do I have to imlement something on my own...

Tnx,
H

推荐答案

这里是使用两个字典的类的示例.
我确实提醒您注意您的第一个条件,因为如果更改值的优先级,我肯定我的解决方案会遇到问题.

Here''s an example of a class that uses two Dictionaries.
I do caution you about your first criterion as I''m sure my solution will have trouble if a value''s priority is changed.

DumbStuff.PriorityDictionary<int,int,string> d =
  new DumbStuff.PriorityDictionary<int,int,string>() ;

d.Add ( 012395 , 0 , "obj8"  ) ;
d.Add ( 892619 , 2 , "obj12" ) ;
d.Add ( 158276 , 2 , "obj3"  ) ;
d.Add ( 198756 , 2 , "obj5"  ) ;
d.Add ( 787362 , 8 , "obj7"  ) ;
d.Add ( 298656 , 9 , "obj4"  ) ;

foreach ( int p in d.PriorityList )
{
  System.Console.Write ( "Priority {0} : " , p ) ;

  foreach ( string s in d.GetByPriority ( p ) )
  {
    System.Console.Write ( " {0}" , s ) ;
  }

  System.Console.WriteLine() ;
}





namespace DumbStuff
{
  public partial class PriorityDictionary<Tkey,Tpriority,Tvalue> : System.IDisposable
  where Tpriority : System.IComparable
  where Tvalue : class
  {
    protected System.Collections.Generic.Dictionary<Tkey,Tvalue> dic ;
    protected System.Collections.Generic.Dictionary<Tpriority,System.Collections.Generic.HashSet<Tvalue>> lis ;

    public PriorityDictionary
    (
    )
    {
      this.dic = new System.Collections.Generic.Dictionary<Tkey,Tvalue>() ;
      this.lis = new System.Collections.Generic.Dictionary<Tpriority,System.Collections.Generic.HashSet<Tvalue>>() ;

      return ;
    }

    public virtual void
    Add
    (
      Tkey      Key
    ,
      Tpriority Priority
    ,
      Tvalue    Value
    )
    {
      this.dic.Add ( Key , Value ) ;

      if ( !this.lis.ContainsKey ( Priority ) )
      {
        this.lis.Add ( Priority , new System.Collections.Generic.HashSet<Tvalue>() ) ;
      }

      this.lis [ Priority ].Add ( Value ) ;

      return ;
    }

    public virtual System.Collections.Generic.IList<Tpriority>
    PriorityList
    {
      get
      {
        System.Collections.Generic.List<Tpriority> result = 
          new System.Collections.Generic.List<Tpriority> ( this.lis.Keys ) ;

        result.Sort() ;

        return ( result.AsReadOnly() ) ;
      }
    }

    public virtual System.Collections.Generic.IList<tvalue>
    GetByPriority
    (
      Tpriority Priority
    )
    {
      System.Collections.Generic.List<tvalue> result =
        new System.Collections.Generic.List<tvalue> ( this.lis [ Priority ] ) ;

      return ( result.AsReadOnly() ) ;
    }

... other members ...


另一种方法(我并不是说这是最好的方法!)

您可能具有< KeyValuePair< string,int> ;, string>的字典.例如,使用您故意更改顺序的数据,现在仅使用字符串作为对象
An alternative approach (I''m not suggesting it''s the best one!)

You could have a Dictionary of <KeyValuePair<string, int>, string>. For example, using your data which I''ve deliberately changed the order on, and just using string for the object for now
var original = new Dictionary<KeyValuePair<string, int>, string>();
original.Add(new KeyValuePair<string, int>("298656", 9), "obj4");
original.Add(new KeyValuePair<string, int>("012395", 0), "obj8");
original.Add(new KeyValuePair<string, int>("892619", 2), "obj12");
original.Add(new KeyValuePair<string, int>("198756", 2), "obj5");
original.Add(new KeyValuePair<string, int>("787362", 8), "obj7");
original.Add(new KeyValuePair<string, int>("158276", 2), "obj3");


创建IComparer< KeyValuePair< string,int>>
的自定义实现


Create a custom implementation of IComparer<KeyValuePair<string, int>>

public class MyKVPCompare : IComparer<KeyValuePair<string, int>>
{
    public int Compare(KeyValuePair<string, int> x, KeyValuePair<string, int> y)
    {
        return x.Value.CompareTo(y.Value);
    }
}


然后,您可以使用LINQ对字典进行排序-在这里,我按照优先级顺序对字典进行了排序,然后按键"


You can then sort your dictionary using LINQ - here I''ve done it in priority order then by the "key"

var sorted = original.OrderBy(kvp => kvp.Key, new MyKVPCompare()).ThenBy(a => a.Key.Key);

如果我使用

foreach (var z in sorted)
    Console.WriteLine("Key: {0}, Priority {1}, Value: {2}", z.Key.Key, z.Key.Value, z.Value);

我得到

Key: 012395, Priority 0, Value: obj8
Key: 158276, Priority 2, Value: obj3
Key: 198756, Priority 2, Value: obj5
Key: 892619, Priority 2, Value: obj12
Key: 787362, Priority 8, Value: obj7
Key: 298656, Priority 9, Value: obj4


补充说明一下,您还可以选择通过键"对列表进行排序,而不是仅通过使用


Meant to add that you also have the option of sorting the list by the "key" rather than priority just by using

var sorted2 = original.OrderBy(kvp => kvp.Key.Key);

,而无需将源集合更改为其他内容.

without changing the source collection to something else.


可以是System.Collections.Generic.SortedDictionary<,>:
https://msdn.microsoft.com/en-us/library/f7fta44c%28v = vs.110%29.aspx [ ^ ].

问题是:集合仅按键排序.您正在谈论通过一个键Priority进行排序,以及通过某个键,整数或字符串进行访问. (怎么可能?这很重要.如果键是整数,请始终使用整数类型,不要使用字符串.)从您的问题出发,不清楚是在谈论相同的事物还是两个不同的事物.您可能意味着优先级是整数,或者可能意味着两个不同的键. PIEBALDconsult为您提供了有关此案例的正确思路,请参阅他的评论.无论如何,如果要按一个键排序并按另一个键(或多个然后一个键)进行访问,则需要创建不同的字典,每种键类型需要单独的字典.您最好使用访问和迭代功能将两种或多种字典封装在一种组合类型上.如果您增加了价值,则应将其添加到两个字典中,依此类推.

—SA
That can be System.Collections.Generic.SortedDictionary<,>:
https://msdn.microsoft.com/en-us/library/f7fta44c%28v=vs.110%29.aspx[^].

The problem is: the collection is sorted by the key only. You are talking about sorting by one key Priority and accessing by some key, integer or string. (How can be no matter? It is very important. If the key is integer, always use integer type, never a string.) From your question, it is not clear if you are talking about the same things or two different ones. You might mean that priority is integer, or you might mean two different keys. PIEBALDconsult gave you correct idea for this case, please see his comment. Anyway, if you want to sort by one key and access by another key (or more then one key), you would need to create different dictionaries, a separate dictionary per key type. You should better encapsulate two or more dictionaries on one composing type with access and iteration capabilities. If you add value, it should be added to both dictionaries and so on.

—SA


这篇关于实现允许多个值的排序的集合/词典的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆