Reputation: 815
I have a
list<int> = {14, 24, 56,189,909,1000};
I want to collapse (group?) them by a range such that the ints that fall within the range of each other are collapse into one value.
So the results should be for range = 100
{14,24,56} //since they 24 falls within 100 of 14 and 56 falls within 100 of 24
{189}
{909, 1000} //since they fall within 100 of each other
I know this is possible using a linq group by but I am stumped by the syntax.
I have looked at this answer but cannot figure out what to use for the ranges, since I have only one range i.e. 100.
int[] values = {100, 110, 120, 130, 140, 150, 160, 170};
int[] ranges = {115, 145, 180};
var query = from value in values
group value by ranges.Where(x => value >= x)
.DefaultIfEmpty()
.Last();
foreach (var group in query)
{
Console.WriteLine("{0}: {{{1}}}", group.Key,
string.Join(", ", group));
}
Upvotes: 0
Views: 834
Reputation: 6016
Your best option is using a plain old for loop instead of linq:
var l = new[] { 14, 24, 56, 189, 909, 1000 };
var groups = new List<List<int>>();
groups.Add(new List<int>());
groups[0].Add(l[0]);
for (int i = 1; i < l.Length; i++)
{
if (l[i] - l[i - 1] > 100)
{
groups.Add(new List<int>());
}
groups[groups.Count - 1].Add(l[i]);
}
Upvotes: 1
Reputation: 61865
Edit: This may not apply, especially with the additional requirement in the comment as it 1) starts each group only at one point and 2) would place 150 only in the first group.
I would probably write it as so because of the "dynamic" range (and I'm not sure how Group By could be used without an equally involved bucket process). This function requires that the input is already sorted.
IEnumerable<IEnumerable<int>> GroupByStartingRange (IEnumerable<int> src) {
int? maybeStart;
while ((maybeStart = src.FirstOrDefault() != null) {
if (maybeStart.HasValue) {
var start = maybeStart.Value;
yield return src.TakeWhile(x => x <= start + 100)
src = src.SkipWhile(x => x <= start + 100);
}
}
}
Upvotes: 1
Reputation: 5835
Assuming your ranges are ordered:
int[] values = { 100, 110, 120, 130, 140, 150, 160, 170 };
int[] ranges = { 115, 145, 180 };
var groups = values.GroupBy(x => ranges.First(r => x <= r));
Upvotes: 0