C# 基于范围数据查找值
什么样的数据结构或数据类型适合保存数据范围,并基于该范围内的数据返回值 例如,假设我有以下范围C# 基于范围数据查找值,c#,.net,C#,.net,什么样的数据结构或数据类型适合保存数据范围,并基于该范围内的数据返回值 例如,假设我有以下范围 1-10 -> 1 11-35 -> 2.5 36-49-> 3.8 50-60 -> 1.2 61-80 -> 0.9 在这种情况下,给定编号41我希望返回编号3.8(因为41介于36和49之间) 为了执行此查找,是否有一种在数据结构中表示此类数据的巧妙方法?您可以使用此代码 关键: 公共类间隔,其中T:i可比较 { 公共可为空的开始{get;set
1-10 -> 1
11-35 -> 2.5
36-49-> 3.8
50-60 -> 1.2
61-80 -> 0.9
在这种情况下,给定编号41
我希望返回编号3.8
(因为41介于36和49之间)
为了执行此查找,是否有一种在数据结构中表示此类数据的巧妙方法?您可以使用此代码
关键:
公共类间隔,其中T:i可比较
{
公共可为空的开始{get;set;}
公共可为空的结尾{get;set;}
公共间隔(T开始,T结束)
{
开始=开始;
结束=结束;
}
公共布尔值范围(T值)
{
返回((!Start.HasValue | | value.CompareTo(Start.value)>0)&&
(!End.HasValue | | End.Value.CompareTo(Value)>0));
}
}
值:十进制
您可以使用以下类型:Dictionary
备注:您可以定义访问方法您可以使用此代码
关键:
公共类间隔,其中T:i可比较
{
公共可为空的开始{get;set;}
公共可为空的结尾{get;set;}
公共间隔(T开始,T结束)
{
开始=开始;
结束=结束;
}
公共布尔值范围(T值)
{
返回((!Start.HasValue | | value.CompareTo(Start.value)>0)&&
(!End.HasValue | | End.Value.CompareTo(Value)>0));
}
}
值:十进制
您可以使用以下类型:Dictionary
注:您可以定义访问方法一个相对方便且性能非常好的实现是使用
分类列表
。使用每个段的下限作为键,并使用上限+映射值的元组作为值:
var list = new SortedList<int, Tuple<int, double>>
{
{ 1, Tuple.Create(10, 1.0) },
{ 11, Tuple.Create(35, 2.5) },
};
此时,索引
指向可能包含值的唯一范围,因此剩下的就是测试:
if(x >= list.Keys[index] && x <= list.Values[index].Item1) {
var result = list.Values[index].Item2;
}
else {
// no match
}
if(x>=list.Keys[index]&&x一个相对方便且性能非常好的实现是使用SortedList
。使用每个段的下界作为键,使用上界+映射值的元组作为值:
var list = new SortedList<int, Tuple<int, double>>
{
{ 1, Tuple.Create(10, 1.0) },
{ 11, Tuple.Create(35, 2.5) },
};
此时,索引
指向可能包含值的唯一范围,因此剩下的就是测试:
if(x >= list.Keys[index] && x <= list.Values[index].Item1) {
var result = list.Values[index].Item2;
}
else {
// no match
}
if(x>=list.Keys[index]&&x我花了一段时间,但我有一个QuickAndDirty方法,它假设所有给定的值都有效,范围相邻,而不使用任何数据结构。
以及一个非常特定的数据结构,它只会在给定的索引正好在指定范围内时返回某些内容,并且可以在运行时进行扩展
public abstract class TreeNode
{
public static double QuickAndDirty(int index)
{
double result = 1.0;
if (index > 10)
result = 2.5;
if (index > 35)
result = 3.8;
if (index > 49)
result = 1.2;
if (index > 60)
result = 0.9;
return result;
}
public abstract double GetValue(int index);
public abstract TreeNode AddRange(int begin, int end, double value);
public static TreeNode MakeTreePart(Tuple<int, int, double>[] ranges)
{
return TreeNode.MakeTreePart(ranges, 0, ranges.Length >> 1, ranges.Length - 1);
}
private static TreeNode MakeTreePart(Tuple<int, int, double>[] ranges, int min, int index, int max)
{
if (index == min || index == max)
return new Leaf(ranges[index].Item1, ranges[index].Item2, ranges[index].Item3);
return new SegmentTree(
ranges[index].Item2 + .5,
TreeNode.MakeTreePart(ranges, min, index >> 1, index - 1),
TreeNode.MakeTreePart(ranges, index + 1, index << 1, max));
}
}
public class SegmentTree : TreeNode
{
private double pivot;
private TreeNode left, right;
public SegmentTree(double pivot, TreeNode left, TreeNode right)
{
this.pivot = pivot;
this.left = left;
this.right = right;
}
public override double GetValue(int index)
{
if (index < pivot)
return left.GetValue(index);
return right.GetValue(index);
}
public override TreeNode AddRange(int begin, int end, double value)
{
if (end < pivot)
this.left = this.left.AddRange(begin, end, value);
else
this.right = this.right.AddRange(begin, end, value);
// Do this to confirm to the interface.
return this;
}
}
public class Leaf : TreeNode
{
private int begin, end;
private double value;
public Leaf(int begin, int end, double value)
{
this.begin = begin;
this.end = end;
this.value = value;
}
public override double GetValue(int index)
{
if (index >= begin && index <= end)
return value;
throw new Exception("index out of range");
}
public override TreeNode AddRange(int begin, int end, double value)
{
if (this.end < begin)
return new SegmentTree(((double)this.end + begin) * .5, this, new Leaf(begin, end, value));
else if (end < this.begin)
return new SegmentTree(((double)end + this.begin) * .5, new Leaf(begin, end, value), this);
else throw new Exception("Indexes overlap.");
}
}
static void Main()
{
TreeNode start = new Leaf(36, 49, 3.8);
start = start.AddRange(11, 35, 2.5);
start = start.AddRange(1, 10, 1.0);
start = start.AddRange(50, 60, 1.2);
start = start.AddRange(61, 80, 0.9);
double[] values = new double[70];
for (int i = 1; i < values.Length; i++)
values[i] = start.GetValue(i);
TreeNode array = TreeNode.MakeTreePart(
new Tuple<int, int, double>[]
{
Tuple.Create(1, 10, 1.0),
Tuple.Create(11, 35, 2.5),
Tuple.Create(36, 49, 3.8),
Tuple.Create(50, 60, 1.2),
Tuple.Create(61, 80, 0.9)
});
for (int i = 1; i < values.Length; i++)
values[i] = start.GetValue(i);
}
公共抽象类树节点
{
公共静态双QuickAndDirty(整数索引)
{
双结果=1.0;
如果(索引>10)
结果=2.5;
如果(索引>35)
结果=3.8;
如果(索引>49)
结果=1.2;
如果(索引>60)
结果=0.9;
返回结果;
}
公共摘要双GetValue(int索引);
公共抽象树节点AddRange(int begin、int end、double value);
公共静态树节点MakeTreePart(元组[]范围)
{
返回TreeNode.MakeTreePart(范围,0,范围.长度>>1,范围.长度-1);
}
私有静态树节点MakeTreePart(元组[]范围,int-min,int-index,int-max)
{
如果(索引==最小值| |索引==最大值)
返回新叶(范围[index].Item1,范围[index].Item2,范围[index].Item3);
返回新的分段树(
范围[索引].Item2+.5,
生成树部件(范围,最小值,索引>>1,索引-1),
MakeTreePart(ranges,index+1,index=begin&&index我花了一些时间,但是我有一个QuickAndDirty方法,它假设所有给定的值都是有效的,并且范围是相邻的,而不使用任何数据结构。
以及一个非常特定的数据结构,它只会在给定的索引正好在指定范围内时返回某些内容,并且可以在运行时进行扩展
public abstract class TreeNode
{
public static double QuickAndDirty(int index)
{
double result = 1.0;
if (index > 10)
result = 2.5;
if (index > 35)
result = 3.8;
if (index > 49)
result = 1.2;
if (index > 60)
result = 0.9;
return result;
}
public abstract double GetValue(int index);
public abstract TreeNode AddRange(int begin, int end, double value);
public static TreeNode MakeTreePart(Tuple<int, int, double>[] ranges)
{
return TreeNode.MakeTreePart(ranges, 0, ranges.Length >> 1, ranges.Length - 1);
}
private static TreeNode MakeTreePart(Tuple<int, int, double>[] ranges, int min, int index, int max)
{
if (index == min || index == max)
return new Leaf(ranges[index].Item1, ranges[index].Item2, ranges[index].Item3);
return new SegmentTree(
ranges[index].Item2 + .5,
TreeNode.MakeTreePart(ranges, min, index >> 1, index - 1),
TreeNode.MakeTreePart(ranges, index + 1, index << 1, max));
}
}
public class SegmentTree : TreeNode
{
private double pivot;
private TreeNode left, right;
public SegmentTree(double pivot, TreeNode left, TreeNode right)
{
this.pivot = pivot;
this.left = left;
this.right = right;
}
public override double GetValue(int index)
{
if (index < pivot)
return left.GetValue(index);
return right.GetValue(index);
}
public override TreeNode AddRange(int begin, int end, double value)
{
if (end < pivot)
this.left = this.left.AddRange(begin, end, value);
else
this.right = this.right.AddRange(begin, end, value);
// Do this to confirm to the interface.
return this;
}
}
public class Leaf : TreeNode
{
private int begin, end;
private double value;
public Leaf(int begin, int end, double value)
{
this.begin = begin;
this.end = end;
this.value = value;
}
public override double GetValue(int index)
{
if (index >= begin && index <= end)
return value;
throw new Exception("index out of range");
}
public override TreeNode AddRange(int begin, int end, double value)
{
if (this.end < begin)
return new SegmentTree(((double)this.end + begin) * .5, this, new Leaf(begin, end, value));
else if (end < this.begin)
return new SegmentTree(((double)end + this.begin) * .5, new Leaf(begin, end, value), this);
else throw new Exception("Indexes overlap.");
}
}
static void Main()
{
TreeNode start = new Leaf(36, 49, 3.8);
start = start.AddRange(11, 35, 2.5);
start = start.AddRange(1, 10, 1.0);
start = start.AddRange(50, 60, 1.2);
start = start.AddRange(61, 80, 0.9);
double[] values = new double[70];
for (int i = 1; i < values.Length; i++)
values[i] = start.GetValue(i);
TreeNode array = TreeNode.MakeTreePart(
new Tuple<int, int, double>[]
{
Tuple.Create(1, 10, 1.0),
Tuple.Create(11, 35, 2.5),
Tuple.Create(36, 49, 3.8),
Tuple.Create(50, 60, 1.2),
Tuple.Create(61, 80, 0.9)
});
for (int i = 1; i < values.Length; i++)
values[i] = start.GetValue(i);
}
公共抽象类树节点
{
公共静态双QuickAndDirty(整数索引)
{
双结果=1.0;
如果(索引>10)
结果=2.5;
如果(索引>35)
结果=3.8;
如果(索引>49)
结果=1.2;
如果(索引>60)
结果=0.9;
返回结果;
}
公共摘要双GetValue(int索引);
公共抽象树节点AddRange(int begin、int end、double value);
公共静态树节点MakeTreePart(元组[]范围)
{
返回TreeNode.MakeTreePart(范围,0,范围.长度>>1,范围.长度-1);
}
私有静态树节点MakeTreePart(元组[]范围,int-min,int-index,int-max)
{
如果(索引==最小值| |索引==最大值)
返回新叶(范围[index].Item1,范围[index].Item2,范围[index].Item3);
返回新的分段树(
范围[索引].Item2+.5,
生成树部件(范围,最小值,索引>>1,索引-1),
MakeTreePart(范围、索引+1、索引=开始和索引)查看或结构(可能后者更适合您的问题)查看或结构(可能后者更适合您的问题)