从当前[Linq]开始按值状态选择字典中的下一个元素(KeyValue)

Selecting next element (KeyValue) in Dictionary by Value state starting from current [Linq]

我很好奇是否有更好看、更简单(?在使用 Linq 的情况下可能有争议 :p)的方法 select 任何下一个不是当前 selected 的字典元素。

假设我有一个 Dictionary<string,bool>,我已经存储了一个 default/first 键,现在我需要 select 下一个具有值 "true" 的元素(并且如果到达终点重新开始)没有foreach/loop循环。

我知道字典没有排序,但我不关心这种情况。只要 nextKey != currentKey 并且搜索从 currentKey 开始,而不是从 FirstOrDefault 开始(除非它是词典的 "the end")我现在很好。

示例:

public Dictionary<string,bool> myDic = new Dictionary<string,bool>(5);
myDic.Add("test1", false);
myDic.Add("test2", true);
myDic.Add("test3", false);
myDic.Add("test4", true);
myDic.Add("test5", true);

现在我select先Key,如果是真的,我单独保存。 否则或根​​据要求 - 我需要从当前 selected 开始找到下一个值为 true 的键。所以假设我 select 使用 ElementAt(1) 而它是 test1。因为 Valuefalse,所以我需要得到下一个 true,即 test2。正如我所说,我想避免像 foreach/for/while/etc.

这样的显式循环

试试这个:

var result = yourDictionary.SkipWhile(_keyValue => _keyValue .Key != currentKey).Where(_keyValue => _keyValue.Value == true);

我要做的只是 select 所有带 value==true 的值,跳到 currentKey 元素,然后获取下一个元素,例如:

public Dictionary<string,bool> myDic = new Dictionary<string,bool>(5);      
myDic.Add("test1", false);
myDic.Add("test2", true);
myDic.Add("test3", false);
myDic.Add("test4", true);
myDic.Add("test5", true);
string currentKey;
KeyValuePair<string,bool> res;
if (currentKey==null)
{
    res=myDic.Where(x => x.Value).FirstOrDefault();
}
else
{
    res=myDic.Where(x => x.Value).SkipWhile(x => x.Key !=             
          currentKey).Skip(1).FirstOrDefault();
}
if (res.Key!=null)
{
     currentKey=res.Key;
     Console.WriteLine(currentKey);
}
else
{
    Console.WriteLine("Result is null");
} 

使用枚举器:

            Dictionary<string, bool> dict = new Dictionary<string, bool>();

            List<string> keys = dict.Keys.AsEnumerable().ToList();
            List<string>.Enumerator dictEnumerator = keys.GetEnumerator();

根据@Abdullah-dibas 的想法,这可能对您有用。

var m = myDic.SkipWhile(x => x.Value && x.Key != myDic.First().Key)?.First();

我看到您使用的是 C# 2.0,因此需要进行更改:

var m = myDic.SkipWhile(x => x.Value && x.Key != myDic.First().Key);
if (m != null && m.Count() > 0)
{
    var element = m.First();
    //And do whatever
}

简单的回答是:不行,你不能不使用任何foreach/loop cycle.
考虑到所有 linq-to-object 代码都是某种 foreach/loop 循环。

但是,如果您不希望在当前页面中看到这些循环,您可以创建这样的扩展方法:

public static TKey GetNextKeyByValue<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, 
    TKey currentKey, TValue nextValue)
{
    var ckFounded = false;
    // if `currentkey` is last key of dictionary it will check for value from start again
    for (var i = 0; i < 2; i++)
    {
        foreach (var pair in dictionary)
        {
            if (ckFounded && pair.Value.Equals(nextValue))
            {
                return pair.Key;
            }
            if (pair.Key.Equals(currentKey) || (currentKey?.Equals(default(TKey)) ?? true))
            {
                ckFounded = true;
            }
        }
    }

    throw new Exception("Key not found");
}

这样使用:

//var nextKey = yourDictionary.GetNextKeyByValue(currentKey, nextValue);
var firstKey = myDic.GetNextKeyByValue(default(string) /* or null */, true);
var nextKey = myDic.GetNextKeyByValue(firstKey, true);