Group by range and include edge duplicates I've created a method that groups Item entities below based on their Value property. The idea is to produce groups that also includes possible &quot;edge duplicates&quot;, i.e.
[{ Value: 9 }, { Value: 10 }, { Value: 11 }]

With rangeSize set to 10 yields two groups:
[ [{ Value: 9 }, { Value: 10 }], [{ Value: 10 }, { Value: 11 }] ]


public IEnumerable&lt;IEnumerable&lt;DTO.Item&gt;&gt; GroupByValueRange(int rangeSize)
{
    var items = _itemRepository.GetAll().ToList();
    var steps = Math.Ceiling(items.Max(p =&gt; p.Value) / rangeSize);
    var groups = new List&lt;IEnumerable&lt;DTO.Item&gt;&gt;();

    for (var i = 1; i &lt;= steps; i++)
    {
        var max = i * rangeSize;
        var min = (i - 1) * rangeSize;
        var currentGroup = items.Where(p =&gt; p.Value &gt;= min &amp;&amp; p.Value &lt;= max);
        groups.Add(currentGroup.Select(p =&gt; _mapper.Map&lt;DTO.Item&gt;(p)));
    }

    return groups;
}

So the idea is to create groups with values like 0-10, 10-20, 20-30 etc...
Can there be empty groups?
If you pass in a rangeSize of 5, your current code will have an empty group. Is this desired?
Iterating over entire collection for each group
In addition to Peter Csala's recommendations, there is a possible performance issue here: you are iterating over the entire source for each group. The delegate passed to Where must be evaluated against all the items, to determine the contents of each group.
for (var i = 1; i &lt;= steps; i++)
{
    ...
    var currentGroup = items.Where(p =&gt; p.Value &gt;= min &amp;&amp; p.Value &lt;= max);
    groups.Add(currentGroup.Select(p =&gt; _mapper.Map&lt;DTO.Item&gt;(p)));
}

If you have few items, or only a small number of groups, this might not be an issue.
The following might be more efficient. Create a sequence of mapped-item / group-index pairs:
public IEnumerable&lt;(DTO.Item mappedItem, int groupIndex)&gt; GroupIndexes(int rangeSize) {
    foreach (var item in _itemRepository.GetAll()) {
        var groupIndex = Math.Floor(item.Value / rangeSize);
        var mapped = _mapper.Map&lt;DTO.Item&gt;(item);
        yield return (mapped, groupIndex);
        if (item.Value &gt; 0 &amp;&amp; item.Value % rangeSize == 0) {
            yield return (mapped, groupIndex - 1);
        }
    }
}

which you could then use to group:
var grouped = GroupIndexes(10).GroupBy(x =&gt; x.groupIndex, x =&gt; x.mappedItem);