Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get subset x elements before and x elements after LINQ

Tags:

c#

.net

linq

I have a list and i need a subset of it which has the 5 previous elements to the one currently in the for loop and 5 elements after, so in total a list of 10 elements. Ignoring the current item in the loop.

I am currently achieving this as follows:

var currentIndex = myList.ClassName.FindIndex(a => a.Id == plate.Id);
var fromIndex = currentIndex - 5;
if (fromIndex < 0) fromIndex = 0;
var toIndex = currentIndex + 5;
if ((myList.ClassName.ElementAtOrDefault(toIndex) == null))
    toIndex = myList.ClassName.Count - 1;


var subsetList = myList.ClassName.GetRange(fromIndex, (11));
comparisonPlates.RemoveAt(currentIndex);

However i am sure there is a much better and more efficient way of doing this using LINQ, any guidance?

like image 781
Tommy Avatar asked Oct 28 '25 13:10

Tommy


1 Answers

I'd suggest you use LINQ to generate indices:

var subset = Enumerable.Range(currentIndex - 5, 5)
    .Concat(Enumerable.Range(currentIndex + 1, 5))
    .SkipWhile(index => index < 0)
    .TakeWhile(index => index < items.Count)
    .Select(index => items[index])
    ;

This can be more efficient than the way using items.Skip operation, because items.Skip(n) will internally do IEnumerator.MoveNext through n elements one by one, that is, the greater your currentIndex, the less efficient.

Of course SkipWhile or TakeWhile in the code above is slightly inefficient for the same reason, but it totally loops always only 10 times. If you hate that inefficiency, you can calculate indices and counts (parameters of Enumerable.Range) beforehand and eliminate those. (In my opinion, my code above seems more readable.)

In addition, Runtime Complexity of the indexer([]) of List is O(1), that means items[index] takes constant time regardless of index value or the size of your List.

like image 91
Ripple Avatar answered Oct 30 '25 04:10

Ripple



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!