簡體   English   中英

在KeyValuePair(C#)中找到最近的鍵

[英]Find Closest Keys In KeyValuePair (C#)

我試圖找到與現有字典相比在順序上最接近的一組元素。 目標是采用包含特定順序的字符串值的第一組元素。 就我而言,我可能有一個更大的列表,看起來像這樣:

{1, "ISO"}
{2, "AEA"}
...
{256, "OI"}
...
{302, "OI"}
{303, "N2"}
{304, "N2.5"}
...
{400, "N2"}

其目的是找到包含特定順序值的鍵值對,並從這些鍵值對中返回LOWEST鍵。 為了使我感到半途而廢,我提取了包含值“ OI”,“ N2”和“ N2.5”的線對的所有可能性。

假設我有一個Dictionary,它的構建如下:

Dictionary map = new Dictionary<int,string>();

map.Add(new KeyValuePair<int, string>(256, "OI");
map.Add(new KeyValuePair<int, string>(302, "OI");
map.Add(new KeyValuePair<int, string>(303, "N2");
map.Add(new KeyValuePair<int, string>(304, "N2.5");
map.Add(new KeyValuePair<int, string>(400, "N2");

我想從此Dictionary中拉出最接近其鍵的元素,以便以升序獲得列表,例如包含302、303和304作為鍵的KeyValuePairs。 最好的方法是什么?

然后我們去:

    Dictionary<int, string> map = new Dictionary<int, string>();

    map.Add(256, "OI");
    map.Add(302, "OI");
    map.Add(303, "N2");
    map.Add(304, "N2.5");
    map.Add(400, "N2");
    var minDiffGroup = map.SelectMany(item1 =>
         map
         .Where(item2 => !object.Equals(item1, item2))
         .Select(item2 => new { Diff = Math.Abs(item1.Key - item2.Key), Item1 = item1, Item2 = item2 })
      )
      .GroupBy(item => item.Diff)
      .OrderBy(group => group.Key)
      .FirstOrDefault();

    Console.WriteLine("Diff: {0}", minDiffGroup.Key);
    foreach (var item in minDiffGroup)
        Console.WriteLine("Item 1: {0}\tItem 2:{1}", item.Item1, item.Item2);
    Console.ReadKey();

輸出:

Diff: 1
Item 1: [302, OI]       Item 2:[303, N2]
Item 1: [303, N2]       Item 2:[302, OI]
Item 1: [303, N2]       Item 2:[304, N2.5]
Item 1: [304, N2.5]     Item 2:[303, N2]

我會進一步幫助您,但是您的問題非常模糊。

編輯

好的,在您添加了更多信息之后,我更改了lamda表達式:

    Dictionary<int, string> map = new Dictionary<int, string>();

    map.Add(256, "OI");
    map.Add(302, "OI");
    map.Add(303, "N2");
    map.Add(304, "N2.5");
    map.Add(400, "N2");
    var orderedMap = map.OrderBy(item => item.Key); // Order the map
    var minDiffGroup = orderedMap.SelectMany(item1 =>
         orderedMap
         .SkipWhile(item2 => !object.Equals(item1, item2)) //skip all elements which were already merged
         .Skip(1) //skip item1 == item2
         .Select(item2 => new { Diff = Math.Abs(item1.Key - item2.Key), Item1 = item1, Item2 = item2 }) //create an unknown type with Key = diff and both items
      )
      .GroupBy(item => item.Diff) //group by Diff
      .OrderBy(group => group.Key) //order by Diff
      .FirstOrDefault(); //Take the smallest group

    if (minDiffGroup?.Count() > 0)
    {
        var lowestChain = minDiffGroup
             .OrderBy(item => item.Item1.Key) //order by the key of item1
             .TakeWhile(item => item.Item1.Key + minDiffGroup.Key == item.Item2.Key) //take all items as long as the next item has the difference of this group (otherwise there is a gap)
             .SelectMany(item => new List<KeyValuePair<int, string>>() { item.Item1, item.Item2 }) //select all collected KeyValuePairs
             .Distinct(); //take every once
        foreach (var item in lowestChain)
        {
            Console.WriteLine(item);
        }
    }

輸出:

[302, OI]
[303, N2]
[304, N2.5]

如果您想同時從中學習,這里是一個基本的快速版本,帶有詳細說明。

總體邏輯是選擇第一個項目,保持迭代直到不再是一個序列。 然后檢查是否至少迭代了2個連續數字(如果可以,請保留並繼續嘗試下一個可用的數字,直到所有數字都被迭代為止)。

Dictionary<int, string> map = new Dictionary<int, string>();

map.Add(256, "OI");
map.Add(302, "OI");
map.Add(303, "N2");
map.Add(304, "N2.5");
map.Add(400, "N2");

// will contain the final results.
Dictionary<int, string> results = new Dictionary<int, string>();

// get map ordered
var mapList = map.OrderBy(o => o.Key).ToList();

// iterate until we have worked out each values
while (mapList.Any())
{
    // take first item
    var item = mapList[0];

    // kepp the index of found consecutive values                             
    var index = 0;

    // loop for each value
    for (int i = 1; i < mapList.Count; i++)
    {
        // if the value isn't 1 higher get out the loop
        if (mapList[i].Key != mapList[index].Key + 1)
        {
            break;
        }
        else
        {
            // value is more than 1 so keep going until we can't
            index++;
        }
    }

    // if we have found at least 2 consecutive numbers
    if (index > 0)
    {
        // add the first of the sequence
        results.Add(item.Key, item.Value);

        // add the rest of the sequence that was found
        for (int i = 0; i < index; i++)
        {
            results.Add(mapList[i + 1].Key, mapList[i + 1].Value);
        }

        // finally removed all items found plus the starting item (hence the + 1)
        mapList.RemoveRange(0, index + 1);
    }
    else
    {
        // no consecutive numbers found so just remove the item so we can loop and try the next one
        mapList.RemoveAt(0);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM