tags:

views:

116

answers:

2

Here is a simplified version of the code I use:

class Program
{
    // Here is the ugly stuff
    static void DoStuff(int[] uidArray)
    {
        int chunkCount = (int)Math.Ceiling(uidArray.Length / 10d);

        for (int i = 0; i < chunkCount; i++)
        {
            // calculating the remaining uids.
            // this is super ugly imho, but I couldnt come up with anything better...
            int remaining = (i == chunkCount - 1) ? uidArray.Length - i * 10 : 10;

            int[] currentChunks = uidArray.Skip(i * 10).Take(remaining).ToArray();
            string[] data = GetDataForUids(currentChunks);

            foreach (string item in data)
            {
                Console.WriteLine(item);
            }
        }
    }

    // Call DoStuff()
    static void Main(string[] args)
    {
        DoStuff(Enumerable.Range(1, 21).ToArray());
        Console.ReadLine();
    }

    // This method does is not my concern
    static string[] GetDataForUids(int[] uidArray)
    {
        var ret = new List<string>();

        foreach (int uid in uidArray)
        {
            ret.Add("item " + uid);
        }

        return ret.ToArray();
    }
}

What the "real" implementation does:

  • taking an int[] of uids
  • dividing them in smaller arrays, with at most 10 uids per part
  • in a for loop taking part by part
  • for each part call GetDataForUids which uses the database in order to fetch the data by uid
  • process the returned data in a foreach loop

Because of the various "outer" variables like chunkCount I cant imagine how this thing can be written in a better way e. g. using LINQ. Is it still possible?

+5  A: 

There you go:

class Program
{
    static void Main(string[] args)
    {
        var uids = Enumerable.Range(1, 21).ToArray();
        var chunks = from index in Enumerable.Range(0, uids.Length)
                     group uids[index] by index / 10;

        foreach (var currentChunks in chunks)
        {
            Console.WriteLine("KEY: {0}", currentChunks.Key);
            // TODO: string[] data = GetDataForUids(currentChunks.ToArray());
            foreach (var uid in currentChunks)
            {
                Console.WriteLine(uid);
            }
        }
    }
}

Prints:

KEY: 0
1
2
3
4
5
6
7
8
9
10
KEY: 1
11
12
13
14
15
16
17
18
19
20
KEY: 2
21
Darin Dimitrov
+1, must admit that using a grouping here is a prettier solution.
driis
A: 

How about:

static void DoStuff(int[] uidArray)
{
    const int length = 10;
    int n = uidArray.Length/length;
    n += n%length == 0 ? 0 : 1;
    IEnumerable<int> parts = uidArray;
    for (int i = 0; i < n; i++ )
    {
        int[] currentChunks = parts.Take(length).ToArray();
        string[] data = GetDataForUids(currentChunks);
        parts = parts.Skip(length);
        foreach (string item in data)
        {
            Console.WriteLine(item);
        }
    }
}

This works because Take will take at most n elements, but return a smaller sequence if there are no more elements.

Slightly prettier version:

static void DoStuff(int[] uidArray)
{
    const int length = 10;
    IEnumerable<int> parts = uidArray;
    while(parts.Any())
    {
        int[] currentChunks = parts.Take(length).ToArray();
        string[] data = GetDataForUids(currentChunks);
        parts = parts.Skip(length);
        foreach (string item in data)
        {
            Console.WriteLine(item);
        }
    }
}
driis