简体   繁体   中英

Find closest value in a list in C# with linq?

I've a list like this:

public List<Dictionary<int, int>> blanks { get; set; }

This keep some index values:

在此处输入图片说明

In addition I have also a variable named X. X can take any value. I want to find closest 'Key' value to X. For example:

If X is 1300, I want to take blanks index: 2 and Key: 1200. How can I do this via linq? Or, is there any other solution?

Thanks in advance.

EDIT: What if it is not a Dictionary. What if it is a List like this:

List<List<int[]>> lastList = new List<List<int[]>>();

在此处输入图片说明

This time, I want to take first List's indexes and second List's index. For example, if X is 800, I want to take 0 and 0 (for index 0) and also take 1 and 1 (for index 1) How can I do this time?

var diffs = blanks.SelectMany((item, index) => item.Select(entry => new
            { 
              ListIndex = index, // Index of the parent dictionary in the list 
              Key = entry.Key, // Key
              Diff = Math.Abs(entry.Key - X) // Diff between key and X
            }));

var closestDiff = diffs.Aggregate((agg, item) => (item.Diff < agg.Diff) ? item : agg);

Dictionary<int, int> closestKeyDict = blanks[closestKey.ListIndex];
int closestKey = closestDiff.Key;
int closestKeyValue = closestKeyDict[closestKey];

The SelectMany clause flattens all the dictionaries entries into a collection of { ListIndex, DictionaryKey, Difference } instances.

This flattened collection is then aggregated to retrieve the item with the minimum difference.

To answer your second questsion:

var diffs = blanks.SelectMany((list, listIndex) => list.
                   SelectMany((array, arrayIndex) => array.
                   Select((item, itemIndex) => new
                   { 
                     ListIndex = listIndex,
                     ArrayIndex = arrayIndex,
                     ItemIndex = itemIndex,
                     Diff = Math.Abs(item - X) 
                   })));

var closestDiff = diffs.Aggregate((agg, item) => (item.Diff < agg.Diff) ? item : agg);

Now in closestDiff you'll find the indices of the closes item (List index, array index and array item index)

This might not be the most optimized way but it should just work,

List<Dictionary<int, int>> blanks = new List<Dictionary<int, int>>
{
    new Dictionary<int, int>{{100,200}},
    new Dictionary<int, int>{{500,200}},
    new Dictionary<int, int>{{700,200}},
    new Dictionary<int, int>{{1200,200}},
    new Dictionary<int, int>{{300,200}},
    new Dictionary<int, int>{{200,200}},
    new Dictionary<int, int>{{800,200}},
};

int x = 1300;

IEnumerable<int> keys = blanks.SelectMany(ints => ints.Keys);
var diff = keys.Select(i => Math.Abs(i - x)).ToList();
var index = diff.IndexOf(diff.Min());
var value = blanks[index].Keys.First();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM