I'm looking for a way to compute the range of a give set of number for example.
if I had H555,H567,H589,H590,H591,H592,H593,H594,H595,H596,H597
I would like output of H555,H567,H589-H597.
I have looked through relevant questions and can not find anything like what I'm looking for.
Thanks
Well, I'd do something like this:
public sealed class Range
{
public int Low { get; private set; }
public int High { get; private set; }
public Range(int low, int high)
{
this.Low = low;
this.High = high;
}
}
Then (completely untested, may not even compile, but hopefully you'll get the drift):
public static IEnumerable<Range> FindRanges(IEnumerable<int> values)
{
using (IEnumerator<int> iterator = values.GetEnumerator())
{
if (!iterator.MoveNext())
{
yield break;
}
int low = iterator.Current;
int high = low;
while (iterator.MoveNext())
{
int next = iterator.Current;
if (next > high + 1)
{
// Previous range (or possibly single value) has finished
yield return new Range(low, high);
low = next;
}
high = next;
}
// Yield trailing range
yield return new Range(low, high);
}
}
I don't think this is particularly easy to do using straight LINQ, to be honest.
EDIT: To adapt this now that everything starts with H, just use:
var numbers = strings.Select(x => int.Parse(x.Substring(1));
var ranges = FindRanges(numbers);
var rangeStrings = ranges.Select(r => r.High == r.Low
? "H" + r.Low : "H" + r.Low + "-" + r.High);
var result = string.Join(",", rangeStrings);
I think that Linq is really overhead here but if you want it here you are:
int[] arr = { 555, 567, 589, 590, 591, 592, 593, 594, 595, 596, 597 };
int gr = 0;
var q = arr
.Skip(1)
.Select((x, i) => new { x, group = (x - arr[i]) == 1 ? gr : gr++ })
.GroupBy( a => a.group)
.Select(
a => a.Count() == 1
? a.First().x.ToString()
: string.Format("{0}-{1}", a.First().x, a.Last().x));
foreach (var item in q)
{
Console.Write(item);
Console.Write(", ");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With