I have an array which is containing 10000 values and I want to take each 50 items from the array and will do some string operations. How should I do it using LINQ or FOR loop. Thanks in advance.
-
1Take a look at this answer (http://stackoverflow.com/a/3210961/259679). – Mohammed Hossain Nov 12 '13 at 17:17
-
I liked some of the solutions here, especially the one where it partitions it into groups of 4 (or 50 in your case) and then operate on each group. Note that you don't need to have a multiple of 50 items in your array. http://stackoverflow.com/questions/9718117/selecting-first-10-records-then-next-10-paging-using-linq – MxLDevs Nov 12 '13 at 17:19
6 Answers
You can use Skip
and Take
in your for
loop, like this:
for (int pos = 0 ; pos < values.Length ; pos += 50) {
var subArray = values.Skip(pos).Take(50).ToArray();
}
Note: this would be extremely inefficient if values
is not an array or a List<String>
.
However, this is not the most efficient way of doing it: you would be better off not using LINQ at all, and use Array.Copy
method instead:
var subArray = new String[50];
for (int pos = 0 ; pos < values.Length ; pos += 50) {
Array.Copy(values, pos, subArray, 0, 50);
}
The above solution requires that subArray
is not stored as part of whatever processing that you are planning to do, and that values.Length
be divisible by 50 (with 10000 items, it is).

- 714,442
- 84
- 1,110
- 1,523
-
1When the input isn't an `IList` this is pretty horribly inefficient, but given that `Skip` has an optimization for `IList`, to which arrays implement, this really isn't bad at all, performance wise. Of course, if you can avoid turning `subArray` into an array, and instead just use it as a sequence, that would improve it a bit. – Servy Nov 12 '13 at 17:20
-
@Servy Thanks, I added a note to mention this potential inefficiency. – Sergey Kalinichenko Nov 12 '13 at 17:21
You can just use GetRange
List<string> elements = yourArray.ToList();
if (null != elements && elements.Count > 50)
{
for (int i = 0; i < elements.Count; i += 50)
{
Array result = elements.GetRange(i,50).ToArray();
// here you can pass the retrived list to your private method to do the necessary functionility.
StringOperationForArray(result);
}
}

- 5,754
- 6
- 26
- 56
-
-
If elements.Count > 50 Then For i As Integer = 0 To elements.Count Step i + 50 Dim result As List(Of String) = elements.GetRange(i, 50) ' here you can pass the retrived list to your private method to do the necessary functionility. StringOperationForList(result) Next End If I tried like above code , but i am getting the following error.. Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection. Thanks for your help – user2982630 Nov 12 '13 at 18:02
Here you go:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication2
{
class Program
{
const int chunkSize = 50;
static void Main(string[] args)
{
var bigList = Enumerable.Range(0, 10000).Select(s => s.ToString()).ToList();
ChunkerProcess(bigList, i => { Console.WriteLine(i); });
}
private static void ChunkerProcess<T>(List<T> bigList, Action<T> action )
{
int pointer = 0;
List<T> chunks = bigList.GetRange(0, chunkSize>bigList.Count?bigList.Count:chunkSize);
while (chunks.Count > 0)
{
foreach (var chunk in chunks)
{
action.Invoke(chunk);
}
chunks.Clear();
if (chunkSize * pointer < bigList.Count)
{
chunks = bigList.GetRange(chunkSize * pointer, chunkSize * (pointer + 1) > bigList.Count ? bigList.Count - chunkSize * pointer : chunkSize);
pointer++;
}
}
}
}
}

- 4,687
- 31
- 47
If you can use Rx Extensions, this would be my favorite solution.
namespace ConsoleApplication2
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
internal class Program
{
#region Constants
private const int chunkSize = 50;
#endregion
#region Methods
private static void Main(string[] args)
{
List<string> bigList = Enumerable.Range(0, 99).Select(s => s.ToString()).ToList();
bigList.ToObservable().Buffer(chunkSize).Subscribe(
chunk =>
{
foreach (string s in chunk)
{
Console.WriteLine(s);
}
Console.WriteLine(String.Empty.PadRight(80, '-'));
});
}
#endregion
}
}
Combined with Parallel Extensions Extras
namespace ConsoleApplication2
{
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Schedulers;
internal class Program
{
#region Constants
private const int ChunkSize = 50;
#endregion
#region Methods
private static void Main(string[] args)
{
var cancellationTokenSource = new CancellationTokenSource();
CancellationToken cancellationToken = cancellationTokenSource.Token;
var workStealingTaskScheduler = new WorkStealingTaskScheduler(Environment.ProcessorCount - 1);
var bag = new ConcurrentBag<Task>();
IEnumerable<string> bigList = Enumerable.Range(0, 10000).Select(s => s.ToString());
bigList.ToObservable().Buffer(ChunkSize).Subscribe(
chunk => bag.Add(
Task.Factory.StartNew(
() =>
{
foreach (string s in chunk)
{
Console.WriteLine(s);
}
Console.WriteLine(String.Empty.PadRight(80, '-'));
},
cancellationToken,
TaskCreationOptions.None,
workStealingTaskScheduler)));
Task.WaitAll(bag.ToArray());
}
#endregion
}
}

- 4,687
- 31
- 47
How is data enumerated actually? If it is IEnumerable
then even foreach
will work fine else if you have List
even then foreach
or IEnumerable.ForEach
is also applicable and there is no extra penalty in performance even by slicing data.
e.g.
foreach(var item in list)
{
//your operation here
}
OR,
list.ForEach(o=>
{
//your operation here
}
);

- 685
- 6
- 16