从当前[Linq]开始的Dictionary by Value状态中选择下一个元素(KeyValue)

时间:2017-09-04 10:59:18

标签: c# linq dictionary unity3d c#-2.0

我很好奇是否有更好看的,更简单的(在Linq:p的情况下可能存在争议)方式来选择当前未选择的任何下一个Dictionary元素。

假设我有一个Dictionary<string,bool>,我已经存储了一个默认/第一个键,现在我需要选择具有值“true”的下一个元素(如果到达结尾则重新开始) 没有foreach / loop 循环。

我知道字典没有订购,但在这种情况下我不在乎。只要nextKey != currentKey和搜索距currentKey更远,而不是从FirstOrDefault开始(除非它是字典的“结尾”)我现在很好。

示例:

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);

现在我选择第一个Key,如果是,我会单独保存。 否则OR或请求 - 我需要找到从当前选中的值开始具有值true的下一个Key。所以我要说我选择使用ElementAt(1),它是test1。由于Valuefalse,我需要获得true的下一个test2get-eventlog -computername dc-01 -logname security | ?{$_.eventid -eq "4674"} | select machinename,eventid,@{n='AccountName';e={$_.ReplacementStrings[1]}},entrytype,message | convertto-html | out-file c:\test.htmlGet-EventLog "Security" -before 4/10/2013 -InstanceId 4663 | % { New-Object psobject -Property @{ Index = $_.Index TimeGenerated = $_.TimeGenerated "Account Name" = $_.ReplacementStrings[1] "Object Type" = $_.ReplacementStrings[5] "Object Name" = $_.ReplacementStrings[6] } } | export-csv c:\export.csv -NoTypeInformation正如我所说,我想避免像foreach / for / while / etc这样的显式循环。

5 个答案:

答案 0 :(得分:2)

我要做的只是用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");
} 

答案 1 :(得分:0)

试试这个:

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

答案 2 :(得分:0)

使用枚举器:

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

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

答案 3 :(得分:0)

有了@ 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
}

答案 4 :(得分:0)

简单回答是:,如果不使用任何 foreach /循环,则无法执行此操作。
考虑所有linq-to-object代码都是某种foreach /循环循环。

但是如果你不想在当前页面内看到这些循环,你可以制作这样的扩展方法:

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);