如何在排序字典中找到两个键之间的点

发布于 2024-10-22 01:01:42 字数 175 浏览 5 评论 0 原文

我有一个排序字典,其中包含作为键/值对的测量数据点。为了确定非测量数据点的值,我想使用对应值的线性插值来推断两个已知键之间的值。一旦我拥有了位于其之间的两个键/值对,我就了解如何计算非测量数据点。我不知道的是如何找出它位于哪些键之间。有没有比“for”循环(我正在考虑函数/LINQ 查询)更优雅的方法来找出我的数据点位于哪两个键之间?

I have a sorted dictionary that contains measured data points as key/value pairs. To determine the value for a non-measured data point I want to extrapolate the value between two known keys using a linear interpolation of their corresponding values. I understand how to calculate the non-measured data point once I have the two key/value pairs it lies between. What I don't know is how to find out which keys it lies between. Is there a more elegant way than a "for" loop (I'm thinking function/LINQ query) to figure out which two keys my data point lies between?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

相权↑美人 2024-10-29 01:01:42

像这样的东西会起作用:

 dic.Keys.Zip(dic.Keys.Skip(1), 
              (a, b) => new { a, b })
         .Where(x => x.a <= datapoint && x.b >= datapoint)
         .FirstOrDefault();

这会使用它们是有序的这一事实来遍历它们的键,并按顺序比较彼此后面的所有两个键 - 因为 LINQ 是惰性的,一旦找到第一个匹配项,遍历就会停止。

Something like this would work:

 dic.Keys.Zip(dic.Keys.Skip(1), 
              (a, b) => new { a, b })
         .Where(x => x.a <= datapoint && x.b >= datapoint)
         .FirstOrDefault();

This traverses they keys using the fact that they are ordered and compares all two keys following each other in order - since LINQ is lazy once you find the first match the traversal will stop.

风为裳 2024-10-29 01:01:42

标准 C# 答案的复杂度都是 O(N)。
有时您只需要相当大的排序集合中的一个小子集。 (所以你没有迭代所有的键)
标准 C# 集合在这里无法为您提供帮助。并且解决方案如下:
http://www.itu.dk/research/c5/ 在 C5 中使用 IntervalHeap馆藏图书馆。此类支持 GetRange() 方法,并且将以 O(log N) 复杂度查找起始键,并以 O(N) 复杂度迭代范围。如果性能至关重要的话,这对于大数据集绝对有用。例如游戏中的空间分区

The standard C# answers are all O(N) complexity.
Sometimes you just need a small subset in a rather large sorted collection. (so you're not iterating all the keys)
The standard C# collections won't help you here. And a solution is as followed:
http://www.itu.dk/research/c5/ Use the IntervalHeap in the C5 collections library. This class supports a GetRange() method and will lookup the startkey with O(log N) complexity and iterate the range with O(N) complexity. Which will be definately useful for big datasets if performance is critical. e.g. Spatial Partitioning in gaming

怪我入戏太深 2024-10-29 01:01:42

您可能会问以下问题:

myDictionary.Keys.Where(w => w > start && w < end)

Possible you're asking about following:

myDictionary.Keys.Where(w => w > start && w < end)
心碎的声音 2024-10-29 01:01:42

常规循环在这里应该没问题:

IEnumerable<double> keys = ...; //ordered sequence of keys
double interpolatedKey = ...;

// I'm considering here that keys collection doesn't contain interpolatedKey

double? lowerFoundKey = null;
double? upperFoundKey = null;

foreach (double key in keys)
{
    if (key > interpolatedKey)
    {
        upperFoundKey = key;
        break;
    }
    else
        lowerFoundKey = key;
}

您可以使用更短但效率较低的代码在 C# 中使用 LINQ 来完成此操作:

double lowerFoundKey = key.LastOrDefault(k => k < interpolatedKey);
double upperFoundKey = key.FirstOrDefault(k => k > interpolatedKey);

为了有效地使用 LINQ,它应该有一个名为 在 F# 中使用参数 2 进行窗口化。它将返回 keys< 中相邻对的 IEnumerable /代码> 集合。虽然 LINQ 中缺少此函数,但常规 foreach 循环应该没问题。

regular loop should be ok here:

IEnumerable<double> keys = ...; //ordered sequence of keys
double interpolatedKey = ...;

// I'm considering here that keys collection doesn't contain interpolatedKey

double? lowerFoundKey = null;
double? upperFoundKey = null;

foreach (double key in keys)
{
    if (key > interpolatedKey)
    {
        upperFoundKey = key;
        break;
    }
    else
        lowerFoundKey = key;
}

You can do it in C# with LINQ with shorter but less effective code:

double lowerFoundKey = key.LastOrDefault(k => k < interpolatedKey);
double upperFoundKey = key.FirstOrDefault(k => k > interpolatedKey);

In order to it efficiently with LINQ it should have a method which is called windowed in F# with parameter 2. It will return an IEnumerable of adjacent pairs in keys collection. While this function is missing in LINQ regular foreach loop should be ok.

心如荒岛 2024-10-29 01:01:42

我认为 SortedDictionary 上没有一个函数可以让您比迭代元素更快地找到所需元素周围的元素。 (+1 到 BrokenGlass 解决方案)

为了能够更快地找到物品,您需要切换到其他结构。即 SortedList 提供类似的功能,但允许索引其 Key 集合,因此您可以使用二进制搜索来查找范围。

I don't think there is a function on SortedDictionary that lets you find elements around the one you need faster than iterating elements. (+1 to BrokenGlass solution)

To be able to find items faster you need to switch to some other structure. I.e. SortedList provides similar functionality but allows to index its Key collection and hence you can use binary serach to find the range.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文