6

I have a list of items and I need to loop through it so that every n (eg. 3) items are first collected and then processed at once at the n'th item.

I'm doing the following:

List<MyObject> smallList = new List<MyObject>(); for (int i = 0; i < largeList.Count; i++) { smallList.Add(largeList[i]); if (i % 3 == 0 || i >= largeList.Count - 3) { //Do somehting with those n items... } smallList.Clear(); } 

Is there a better way to do the above?

4 Answers 4

12

You can also do this with LINQ:

var largeList = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); for (int i = 0; i < largeList.Count; i += 3) { var items = largeList.Skip(i).Take(3).ToList(); // do stuff with your 3 (or less items) } 
Sign up to request clarification or add additional context in comments.

5 Comments

This might do a lot of full enumerations of the whole largeList.
You should start at i=0, otherwise you miss the first three.
@Toxantron indeed, fixed.
@Evk I'm pretty sure that List implements the Skip method in a constant time returning some lazy iterator.
@Kajacx yes you are right. Still good to avoid solutions that might enumerate big lists many times under certain conditions. After all that is not much better than simple for loop.
2

You can do it with LINQ.

First, "attach" an index to each item:

var indexedItems = largeList.Select((item, index) => new {index, item}); 

Now group them by their index, while selecting the collection (IEnumerable) of items for each group member:

var groupedItems = indexedItems.GroupBy(indexedItem => indexedItem.index / 3, indexedItem => indexedItem.item, (key, items) => items); 

Now process each group

foreach(var items in groupedItems) { // and optionally, .ToList() to have a List<T> instead of IEnumerable<T> var itemsList = items.ToList(); } 

And altogether...:

var indexedItems = largeList.Select((item, index) => new {index, item}); var groupedItems = indexedItems.GroupBy(indexedItem => indexedItem.index / 3, indexedItem => indexedItem.item, (key, items) => items); foreach(var items in groupedItems) { // Use the items... } 

2 Comments

Looks not much better than for loop :)
@Evk - I agree... I modified it to be more efficient, but I still don't see a reason not use a simple loop.
1

I suggest using nested loops. Not as pretty as LinQ, but certainly faster.

const int n = 3; var small = new List(); for(var i=0; i<large.Count; i+=n) { small.Clear(); for(var j=i; j < n && j<large.Count; j++) small.Add(large[j]); // Do stuff with small } 

However quite similar to what you have now. I think it doesn't get much butter than what you have.

Comments

0

you can use this code:

var MyObjectList = new List<MyObject>(); MyObjectList.Where(a => MyObjectList.IndexOf(a) % 3 == 0).ToList().ForEach(a => { // do your things! }); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.