简体   繁体   English

如何从SortedDictionary获取以前的密钥?

[英]How do I get previous key from SortedDictionary?

I have dictionary containing key value pairs. 我有包含键值对的字典。

SortedDictionary<int,int> dictionary=new SortedDictionary<int,int>();
dictionary.Add(1,33);
dictionary.Add(2,20);
dictionary.Add(4,35);

I want to get previous key value pair from a known key value. 我想从已知的键值获取先前的键值对。 In the above case, if I have key 4, then how can I get <2,20> ? 在上面的例子中,如果我有键4,那我怎么能得到<2,20>

It's hard to implement this efficiently with a SortedDictionary<TKey, TValue> since it is implemented as a binary search tree that does not expose predecessors or successors. 使用SortedDictionary<TKey, TValue>很难有效地实现它SortedDictionary<TKey, TValue>因为它是作为二进制搜索树实现的,不会暴露前辈或后继者。

You could of course just enumerate each KeyValuePair until you find the "known" key. 您当然可以枚举每个KeyValuePair,直到找到“已知”密钥。 With a little bit of LINQ, this would look like (assuming the key definitely exists and isn't the first key): 使用一点LINQ,这看起来像(假设密钥肯定存在并且不是第一个密钥):

SortedDictionary<int, int> dictionary = ...
int knownKey = ...

var previousKvp = dictionary.TakeWhile(kvp => kvp.Key != knownKey)
                            .Last();

If those assumptions don't hold, you could do: 如果这些假设不成立,您可以这样做:

var maybePreviousKvp = dictionary.TakeWhile(kvp => kvp.Key != knownKey)
                                 .Cast<KeyValuePair<int, int>?>()
                                 .LastOrDefault();

(Check that maybePreviousKvp != null to ascertain that the previous KeyValuePair was retrieved successfully.) (检查maybePreviousKvp != null以确定先前的KeyValuePair已成功检索。)

But this isn't going to be efficient at all. 但这根本不会有效。


If feasible, consider using a SortedList<TKey, TValue> instead (obviously, this may not be possible if you can't take its slower inserts and deletes). 如果可行,请考虑使用SortedList<TKey, TValue> (显然,如果您不能采用较慢的插入和删除,这可能是不可能的)。 This collection supports efficient key and value-retrieval by ordered index since it is implemented as a growable array. 此集合支持通过有序索引进行有效的键和值检索,因为它是作为可增长的数组实现的。 Then your query becomes as simple as: 然后您的查询变得如此简单:

SortedList<int, int> dictionary = ...
int knownKey = ...

int indexOfPrevious = dictionary.IndexOfKey(knownKey) - 1;

// if "known" key exists and isn't the first key
if(indexOfPrevious >= 0)
{
   // Wrap these in a KeyValuePair if necessary
   int previousKey = dictionary.Keys[indexOfPrevious];
   int previousValue = dictionary.Values[indexOfPrevious];      
}

IndexOfKey runs a binary search on the keys-list, running in O(log n) time. IndexOfKey在keys-list上运行二进制搜索,在O(log n)时间内运行。 Everything else should run in constant time, meaning the entire operation should run in logarithmic time. 其他所有东西都应该在恒定的时间内运行,这意味着整个操作应该以对数时间运行。


Otherwise, you'll have to implement yourself / find a BST collection that does expose predecessors / successors. 否则,您将必须实现自己/找到确实暴露前任/后继者的BST集合。

I was also looking for an answer to this problem, and I thought a better solution than all of the answers here is to use the TreeDictionary<K, V> from the C5 Collections ( GitHub / NuGet ), which is an implementation of a red-black tree. 我也在寻找这个问题的答案,我认为比这里的所有答案更好的解决方案是使用来自C5集合GitHub / NuGet )的TreeDictionary<K, V> ,这是一个红色的实现 - 黑树。

It has Predecessor / TryPredecessor and WeakPredessor / TryWeakPredecessor methods (as well as equivalent methods for successors) which does exactly what you want. 它具有Predecessor / TryPredecessorWeakPredessor / TryWeakPredecessor方法(以及后继的等效方法),它可以完全满足您的需求。

For example: 例如:

TreeDictionary<int,int> dictionary = new TreeDictionary<int,int>();
dictionary.Add(1,33);
dictionary.Add(2,20);
dictionary.Add(4,35);

// applied to the dictionary itself, returns KeyValuePair<int,int>
var previousValue = dictionary.Predecessor(4);
Assert.Equals(previousValue.Key, 2);
Assert.Equals(previousValue.Value, 20);

// applied to the keys of the dictionary, returns key only
var previousKey = dictionary.Keys.Predecessor(4);
Assert.Equals(previousKey, 2);

// it is also possible to specify keys not in the dictionary
previousKey = dictionary.Keys.Predecessor(3);
Assert.Equals(previousKey, 2);
KeyValuePair<int, int> lookingForThis = dictionary
  .Reverse()
  .SkipWhile(kvp => kvp.Key != 4)
  .Skip(1)
  .FirstOrDefault();

Dictionary<TKey,TValue> is unsorted, so there is no previous thing for some item. Dictionary<TKey,TValue>是未排序的,因此某些项目没有先前的内容。 Instead you can use SortedDictionary<TKey,TValue> . 相反,您可以使用SortedDictionary<TKey,TValue>

EDIT: Sorry I read the title only LOL. 编辑:对不起,我只阅读标题LOL。

If you have to use LINQ: 如果你必须使用LINQ:

int givenKey = 4;
var previousItem = dict.Where((pair, index) => 
                                   index == dict.Count || 
                                   dict.ElementAt(index + 1).Key == givenKey)
                       .FirstOrDefault();

You could loop through the dictionary and keep track of values, I guess. 我想你可以遍历字典并跟踪值。 Something like this: 像这样的东西:

public int GetPreviousKey(int currentKey, SortedDictionary<int, int> dictionary)
{
    int previousKey = int.MinValue;
    foreach(KeyValuePair<int,int> pair in dictionary)
    {
        if(pair.Key == currentKey)
        {
            if(previousKey == int.MinValue)
            {
                throw new InvalidOperationException("There is no previous key.");
            }
            return previousKey;
        }
        else
        {
            previousKey = pair.Key;
        }
    }
}

However, this is a pretty odd operation to require. 但是,这是一个非常奇怪的操作要求。 The fact that you need it might be pointing at a problem with your design. 您需要它的事实可能指向您的设计的问题。

I would prefer to use linq if that's the case... try this it will surely work 如果是这样的话,我宁愿使用linq ...试试这肯定会有用

SortedDictionary<int,int> dictionary = new SortedDictionary<int,int>();
dictionary.add(1, 33);
dictionary.add(2, 20);
dictionary.add(4, 35);

int SelectedKey = 4;

var ResutValue = ( from n in dictionary    
               where n.Key < TheSelectedKey
               select n.Value).Last();

this.txtResult.Text = ResultValue.ToString();

How about this? 这个怎么样? I havent tested it though, but should give something to start think in this direction. 我没有测试过,但是应该从这个方向开始思考。 Hope it helps. 希望能帮助到你。

        int input = 4;
        List<int> lKeys = dictionary.Keys.ToList();
        int reqIndex = lKeys.IndexOf(input) - 1;
        int reqAnswer = dictionary[reqIndex];

test for other conditions like if (reqIndex != -1) etc.. 测试其他条件,如if(reqIndex!= -1)等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从SortedDictionary中删除一个键 - How to remove a key from SortedDictionary 如何从 SortedDictionary 中获取离我的键最近的项目? - How to get the closest item to my key from a SortedDictionary? 从SortedDictionary获取等于项的键? - Get a key equal to an item from SortedDictionary? 如何从SortedDictionary获取整数值的总计? - How can I get running totals of integer values from a SortedDictionary? 如何从SortedDictionary获取最大/最小值? - How to get the maximum/minimum value from a SortedDictionary? 每当我在WPF中的SortedDictionary中添加或删除项目时,如何使列表框自动反映 - How do i make a listbox auto reflect every time i add or remove items from a SortedDictionary in WPF 如何在 C# 中使用 LINQ 从字典转换为 SortedDictionary? - How do I convert from a Dictionary to a SortedDictionary using LINQ in C#? 如何使用Eval()引用ASP中继器中SortedDictionary中的值? - How do I use Eval() to reference values in a SortedDictionary in an asp Repeater? 如何比较来自一个 SortedDictionary 的值以将它们添加到新的 SortedDictionary? - How to compare values from one SortedDictionary to Add them to a new SortedDictionary? 从 SortedDictionary 中查找具有最大值的键? - Find key with max value from SortedDictionary?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM