The easiest way would be something like this:
var result = data
.GroupBy(d => d.SomeValue > 1 ? 0 : d.ID);
Assuming ID
is an int
property that is unique among the items in your collection. Of course can adapt this technique pretty easily to work with if you've got a unique string property, etc. If you have no unique property, you can always do something like this:
var result = data
.Select((d, i) => new { d, i })
.GroupBy(x => x.d.SomeValue > 1 ? -1 : x.i, x => x.d);
This will work in Linq-to-Objects, but I'm not sure about other Linq providers (e.g. Linq-to-SQL, Linq-to-Entities). For those cases, D Stanley's answer might be the only way to go, but for simple Linq queries, this would be more efficient than generating a random Guid
for every non-grouped item.
Of course, if this seems inelegant, you could always wrap it in an extension method. Note that I return an IEnumerable<IEnumerable<T>>
rather than IEnumerable<IGrouping<TKey, T>>
, since the key really is not relevant here anyway:
public static IEnumerable<IEnumerable<T>> GroupWhere<T>(
this IEnumerable<T> set,
Func<T, bool> grouping)
{
return set
.Select((d, i) => new { d, i })
.GroupBy(x => grouping(x.d) ? -1 : x.i, x => x.d);
}
Or this, which, which is has slightly different semantics (grouped items always appear last) but should be bit more efficient:
public static IEnumerable<IEnumerable<T>> GroupWhere<T>(
this IEnumerable<T> set,
Func<T, bool> grouping)
{
List<T> list = new List<T>();
foreach(var x in set)
{
if (!grouping(x))
{
yield return new[] { x };
}
else
{
list.Add(x);
}
}
yield return list;
}
Either way you can use this just like this:
var result = data.GroupWhere(d => d.SomeValue > 1);