我目前(概念上)有:
IEnumerable<Tuple<long, long, Guid>>
给定long
,我需要找到“对应的”GUID
。
long
s对不应该重叠,尽管对之间可能存在间隙,例如:
1, 10, 366586BD-3980-4BD6-AFEB-45C19E8FC989
11, 15, 920EA34B-246B-41B0-92AF-D03E0AAA2692
20, 30, 07F9ED50-4FC7-431F-A9E6-783B87B78D0C
对于每个输入long
,应该有0
或1
匹配GUID
s。
因此7
的输入应返回366586BD-3980-4BD6-AFEB-45C19E8FC989
16
的输入应返回null
更新:我有大约90K对
如何将此内存存储在内存中以便快速搜索?
由于
答案 0 :(得分:6)
只要它们按顺序存储,你就可以根据“范围的开始”和候选者进行二进制搜索。一旦找到具有最大“范围开始”的条目,该条目小于或等于您的目标数字,那么您已经找到了具有正确GUID的条目,或者您已经证明您已经命中了差距(因为范围开始较小的条目的范围 end 的范围低于目标)。
您可以通过使其成为Dictionary<long, Guid?>
来简单地简化逻辑,并且只记录起点,为每个间隙添加一个空值的条目。然后,您只需要找到最高键小于或等于目标数的条目,然后返回该值。
答案 1 :(得分:2)
试试这个(对不起,不是IEnumerable的解决方案):
public static Guid? Search(List<Tuple<long, long, Guid>> list, long input)
{
Tuple<long, long, Guid> item = new Tuple<long,long,Guid> { Item1 = input };
int index = list.BinarySearch(item, Comparer.Instance);
if (index >= 0) // Exact match found.
return list[index].Item3;
index = ~index;
if (index == 0)
return null;
item = list[index - 1];
if ((input >= item.Item1) && (input <= item.Item2))
return item.Item3;
return null;
}
public class Comparer : IComparer<Tuple<long, long, Guid>>
{
static public readonly Comparer Instance = new Comparer();
private Comparer()
{
}
public int Compare(Tuple<long,long,Guid> x, Tuple<long,long,Guid> y)
{
return x.Item1.CompareTo(y.Item1);
}
}
答案 2 :(得分:1)
B树实际上相当不错。具体来说,一个B + -tree,其中每个分支指针都以您的范围的开头为关键字。叶数据可以包含上限,因此您可以正确处理间隙。我不确定它是否是你能在任何地方找到的最好的,你需要自己设计它,但它当然应该有非常好的性能。