Reputation: 127
I would like to ask you if there's a way by Linq to check discontinuity of multiple ranges, for example we have a class AgeRange:
public class AgeRange
{
public int firstValue {get;set;}
public int secondValue {get;set;}
}
var ageRange1 = new AgeRange(0,2); // interval [0,2]
var ageRange2 = new AgeRange(4,10); // interval [4,10]
var ageRange3 = new AgeRange(11,int.MaxValue); // interval [11,+oo[
var ageRangeList = new List<AgeRange>();
ageRangeList.Add(ageRange1);
ageRangeList.Add(ageRange2);
ageRangeList.Add(ageRange3);
in this example we have a discontinuity between first range and second range. is there a way in Linq to check discontinuity between elements in ageRangeList ? Thanks for you help.
Upvotes: 0
Views: 297
Reputation: 11293
If you want to find first discontinuity and use that information elsewhere
public static IEnumerable<AgeRange> FindDiscontinuity(List<AgeRange> ageRangeList) {
foreach(var ageRange in ageRangeList.Zip(ageRangeList.Skip(1), (a, b) => new {Prev = a, Current = b})) {
if(ageRange.Prev.SecondValue != ageRange.Current.FirstValue) {
yield return ageRange.Prev;
yield return ageRange.Current;
break;
}
}
}
public static void Main()
{
var ageRange1 = new AgeRange(0, 2);
var ageRange2 = new AgeRange(4, 10);
var ageRange3 = new AgeRange(11, int.MaxValue);
var ageRangeList = new List<AgeRange>();
ageRangeList.Add(ageRange1);
ageRangeList.Add(ageRange2);
ageRangeList.Add(ageRange3);
var result = FindDiscontinuity(ageRangeList);
foreach(var ageRange in result) {
Console.WriteLine("{0}, {1}", ageRange.FirstValue, ageRange.SecondValue);
}
}
You can change the function so it can return boolean value instead of data.
Upvotes: 0
Reputation: 142833
Assuming firstValue
always <= secondValue
(for the same element), you can try to use Aggregate
:
var start = ageRangeList
.OrderBy(a => a.firstValue).Dump()
.First();
var result = ageRangeList
.OrderBy(a => a.firstValue)
.Aggregate(
(hasGap: false, s: start.secondValue),
(tuple, range) =>
{
if (tuple.hasGap)
{
return tuple;
}
else
{
var max = Math.Max(tuple.s, tuple.s+1); //hacky overflow protection
if (max < range.firstValue)
{
return (true, tuple.s);
}
else
{
return (false, Math.Max(tuple.s, range.secondValue));
}
}
})
.hasGap;
The downside of such approach is that it still will need to loop through all age ranges.
Upvotes: 1