我有三种数值范围,它们在某个区间内定义如下:
1.计数范围(指定范围内的任何值)
2.定期序列(指定序列开始,步骤和步骤计数)
3.一组精确值(如1,3,7等)
我需要将它们联合/交叉(从2到N的不同类型)并获得优化结果。显然,上面的交点将返回上述类型的结果并将它们联合起来将产生上述1到M种类型。
例1:
第一个范围定义为5到11的连续范围,第二个范围定义为2到18的定期序列,步骤2(因此,8个步骤)。
交叉点将返回从步骤2到6的周期序列。
联盟将返回三个结果:从步骤2的2到4的周期性序列,从5到11的连续范围以及从步骤2到12到18的周期序列。
例2:
第一个范围定义为周期序列0到10,步骤2和第二个周期序列从1到7,步骤2(因此,3个步骤)。
交叉点将返回null,因为它们不相交
Union将返回两个结果:1到8的周期序列,步骤1(注意:优化结果)和精确值10
希望我没有犯错误:)
那么,这些序列上的这些操作不应该太复杂,我希望有一个像这里的东西的库。请建议任何(将在C#.NET中使用)
谢谢!
更新
回答“我怎么认为我使用图书馆”。以上三种类型都可以用编程语言轻松定义为:
1. Contionous:{decimal Start;小数结束;其中Start是范围的开始,End是结束
2.期刊:{decimal Start;小数步; int Count;其中Start是序列的开头,Step是递增,Count是步数
3.精确数字集:{decimal []值;其中Values是一些小数的数组。
当我在上面列出的任何类型的任何两个范围的交集时,我肯定会得到其中一种类型的结果,例如“连续”和“期刊”范围交叉将导致“期刊”,“续”。并且“精确的集合”将导致精确的“续”。而“确切”也将返回精确。相同类型的交点将返回输入类型的结果 2个范围的联合稍微复杂一些,但无论如何也会返回上面类型中定义的2到3个范围 具有交集/并集功能,我将始终能够在2到N个范围内运行它,并且将以输入类型术语获得结果。
答案 0 :(得分:2)
首先,遵循之前的其他答案:我不相信有一个标准的库:它看起来非常特殊。
其次,问题/要求没有明确说明。我将按照问题介绍并参考3种不同的类型,如“set”,“periodic”,“continuous”。
考虑两组{1,4,5,6}和{4,5,6,8}。他们的交集是{4,5,6}。我们是否必须将其标记为“周期性”,因为该描述符合大小写,或者作为“set”,因为它是集合的交集?
从这一点来看,一般来说,我们是否需要在其内容为周期性时将“set”标签更改为“periodic”?毕竟,“周期性”是“集合”的特殊情况。
同样,考虑“周期性”{4,6,8}和一组{10,15,16}的联合。我们是否必须将结果定义为周期性{4,6,8,10}加上周期性{15,16}或者更确切地说是一组包含所有值,还是另一种变体?
堕落情况如何:{3}是“集合”,“定期”,甚至是“连续”?什么类型是“连续”{1-4}和“集合”{4,7,8}的交集?连续{1-4}和连续{4-7}?
的交集依此类推:必须清楚的是,必须如何标记/描述任何结果 - 来自联合和/或交叉 - 无论是 - 例如 - 两个离散类型(非连续)的交集或并集总是一个类型(通常是一组,可能是一个周期),或者更确切地说是一系列的周期,或者......
第三,假设上述问题已经得到解决,我相信您可以按照以下准则来实施:
只考虑两种“类型”,即“连续”和“设置”。 “周期性”只是“集合”的一种特殊形式,在任何时候我们都可以在适当的时候将“集合”标记为“周期性”。
定义一个公共基类,并使用适当的派生(交叉)方法进行联合,交集和任何你可能需要的方法,以产生 - 例如 - 一个(baseType)列表作为结果。
< / LI>逐案实现基本上非常简单 - 假设我的介绍性问题已得到解答。只要最初的问题看起来有些“困难”,只是因为问题和规范还没有很好地定义。
答案 1 :(得分:0)
所有听起来都非常习惯 - 所以我认为你不会找到一个可以完成所有这些工作的图书馆 - 但那里没什么太难的。
我会开始你的。对于第一个示例工作正常,但方法Range.ConstructAppropriate
将需要特别复杂,以返回“从步骤2的2到4的周期序列,从5到11的连续范围和来自的周期序列12到18,步骤2 “来自集合{ 5, 6, 7, 8, 9, 10, 11, 2, 4, 12, 14, 16, 18 }
,这是由示例1中两个集合的结合产生的。
另外(在连接所有代码的麻烦之后)我从评论中注意到你需要非整数。这使事情复杂化。我想你可以想出一种创造性的方式来应用这种模式。
class Program
{
static void Main(string[] args)
{
// Example 1:
// 1st range is defined as continous range from 5 to 11 and 2nd is periodical sequence from 2 to 18 with step 2 (thus, 8 steps).
// Intersection will return a periodic sequence from 6 to 10 with step 2.example 1
ContinuousRange ex1_r1 = new ContinuousRange(5, 11);
PeriodicRange ex1_r2 = new PeriodicRange(2, 2, 8);
IEnumerable<int> ex1_intersection = ex1_r1.Values.Intersect(ex1_r2.Values);
IList<Range> ex1_intersection_results = Range.ConstructAppropriate(ex1_intersection);
}
}
abstract class Range
{
public abstract IEnumerable<int> Values { get; }
public static IList<Range> ConstructAppropriate(IEnumerable<int> values)
{
var results = new List<Range>();
results.Add(ContinuousRange.ConstructFrom(values));
results.Add(PeriodicRange.ConstructFrom(values));
if (!results.Any(r => r != null))
results.Add(Points.ConstructFrom(values));
return results.Where(r => r != null).ToList();
}
}
class ContinuousRange : Range
{
int start, endInclusive;
public ContinuousRange(int start, int endInclusive)
{
this.start = start;
this.endInclusive = endInclusive;
}
public override IEnumerable<int> Values
{
get
{
return Enumerable.Range(start, endInclusive - start + 1);
}
}
internal static ContinuousRange ConstructFrom(IEnumerable<int> values)
{
int[] sorted = values.ToArray();
if (sorted.Length <= 1)
return null;
for (int i = 1; i < sorted.Length; i++)
{
if (sorted[i] - sorted[i - 1] != 1)
return null;
}
return new ContinuousRange(sorted.First(), sorted.Last());
}
}
class PeriodicRange : Range
{
int start, step, count;
public PeriodicRange(int start, int step, int count)
{
this.start = start;
this.step = step;
this.count = count;
}
public override IEnumerable<int> Values
{
get
{
var nums = new List<int>();
int i = start;
int cur = 0;
while (cur <= count)
{
nums.Add(i);
i += step;
cur++;
}
return nums;
}
}
internal static Range ConstructFrom(IEnumerable<int> values)
{
// check the difference is the same between all values
if (values.Count() < 2)
return null;
var sorted = values.OrderBy(a => a).ToArray();
int step = sorted[1] - sorted[0];
for (int i = 2; i < sorted.Length; i++)
{
if (step != sorted[i] - sorted[i - 1])
return null;
}
return new PeriodicRange(sorted[0], step, sorted.Length - 1);
}
}
class Points : Range
{
int[] nums;
public Points(params int[] nums)
{
this.nums = nums;
}
public override IEnumerable<int> Values
{
get { return nums; }
}
internal static Range ConstructFrom(IEnumerable<int> values)
{
return new Points(values.ToArray());
}
}