0

I can half-@ss this, but I want a clean way of doing it that wouldn't create any sort of hassle to deal with later.

private String[][] SplitInto10(string[] currTermPairs)
{
   //what do i put in here to return 10 string arrays
   //they are all elements of currTermPairs, just split into 10 arrays.
}

So I basically want to split a string array (currTermPairs) equally into 10 or 11 different string arrays. I need to make sure NO DATA is lost and all the elements are successfully transferred

edit: you're given a string array of n size. what needs to happen is the method needs to return 10 string arrays/lists from the given string array. In other words, split the array into 10 parts.

For example, if i have

 A B C D E F G H I J K L M N O P Q R S T U

i need it to split into 10 string arrays or 11 string arrays depending on the size, so in this case i would have

A B
C D
E F
G H 
I J
K L
M N 
O P 
Q R 
S T 
U   <--Notice this is the 11th array and it is the remainder
Austin Salonen
  • 49,173
  • 15
  • 109
  • 139
Ramie
  • 1,171
  • 2
  • 16
  • 35
  • 2
    Given: _____ Expected: ______ – Austin Salonen Jan 10 '13 at 15:22
  • i don't get it? if you're asking me what is given and what's expected, you can see in the method a string array is given, and it is expected that it is split into 10 different parts equally – Ramie Jan 10 '13 at 15:23
  • @Ramie: We don't know what requirements you have. What is the expected output of some given input? – Patrick Jan 10 '13 at 15:24
  • If your naming conventions are correct, why do you have something named pairs in a `string[]` if something were to be a pair, surely you'd use `Dictionary`? – LukeHennerley Jan 10 '13 at 15:26
  • edited it, to make it more clear – Ramie Jan 10 '13 at 15:26
  • How do you halv-@ss something? – default Jan 10 '13 at 15:26
  • it's when you don't give a shxt about the future problems it can bring up, and you just straight up do it so it works this moment. for example, i might write it in an inefficient way and then when the array size gets too big it turns into bottleneck code – Ramie Jan 10 '13 at 15:29
  • Give us an example we can test code against. What is in `currTermPairs`? Does the order matter? What's the expected result? – Bobson Jan 10 '13 at 15:30
  • This is one way of doing it: http://stackoverflow.com/questions/1349491/how-can-i-split-an-ienumerablestring-into-groups-of-ienumerablestring – Icarus Jan 10 '13 at 15:32
  • 2
    @Ramie: You still haven't told us what the expected output is given some specific input. What does "split equally" mean for you, it might not be the same as what everyone else thinks? Otherwise `return new Random().Next() == 1 ? new string[10] : new string[11]` is valid, given your current requirement. – Patrick Jan 10 '13 at 15:33
  • @Ramie: Good, so, given your example, is it true that currTermPairs is always either 20 or 21 items long? And should the second element be appended to the first element with a space inbetween? – Patrick Jan 10 '13 at 15:39
  • no its not always 20 or 21, can be any number – Ramie Jan 10 '13 at 15:43
  • possible duplicate of [Split List into Sublists with LINQ](http://stackoverflow.com/questions/419019/split-list-into-sublists-with-linq) – nawfal Feb 18 '13 at 12:07

6 Answers6

5

Use the remainder % operator instead, here the Linq approach:

string[][] allArrays = currTermPairs
            .Select((str, index) => new { str, index })
            .GroupBy(x => x.index % 10)
            .Select(g => g.Select(x => x.str).ToArray())
            .ToArray();

Demo (with 2 strings per array)

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • testing this now. What will it do for example if i had 7 elements in the currTermPairs array? Would it put it into the previous one and make it have 3 elements or would it make a whole new array for it? – Ramie Jan 10 '13 at 15:38
  • 1
    The first would get 4 and the second 3 (in my example with two arrays). – Tim Schmelter Jan 10 '13 at 15:40
2

This is a solution not using LINQ, in case you want to get used to arrays and for-loops:

// Determine the number of partitions.
int parts = currTermPairs.Length < 10 ? currTermPairs.Length : 10;

// Create the result array and determine the average length of the partitions.
var result = new string[parts][];
double avgLength = (double)currTermPairs.Length / parts;

double processedLength = 0.0;
int currentStart = 0;
for (int i = 0; i < parts; i++) {
    processedLength += avgLength;
    int currentEnd = (int)Math.Round(processedLength);
    int partLength = currentEnd - currentStart;
    result[i] = new string[partLength];
    Array.Copy(currTermPairs, currentStart, result[i], 0, partLength);
    currentStart = currentEnd;
}
return result;

The total number of items might not be divisible by 10. The question is how the different lengths of the parts will be distributed. Here I try to distribute them evenly. Note the casting (double)currTermPairs.Length. This is necessary in order to get a floating point division instead of an integer division.

Here is a little test method:

const int N = 35;
var arr = new string[N];
for (int i = 0; i < N; i++) {
    arr[i] = i.ToString("00");
}

var result = new PatrtitioningArray().SplitInto10(arr);
for (int i = 0; i < result.Length; i++) {
    Console.Write("{0}:   ", i);
    for (int k = 0; k < result[i].Length; k++) {
        Console.Write("{0}, ", result[i][k]);
    }
    Console.WriteLine();
}

Its output is (with 35 elements):

0:   00, 01, 02, 03, 
1:   04, 05, 06, 
2:   07, 08, 09, 
3:   10, 11, 12, 13, 
4:   14, 15, 16, 17, 
5:   18, 19, 20, 
6:   21, 22, 23, 
7:   24, 25, 26, 27, 
8:   28, 29, 30, 31, 
9:   32, 33, 34, 
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
0

I'd say create a List<List<string>> containing 10 or 11 (whichever number you actually want) List<string>s, and do something like this:

int i = 0;
int index;
foreach(string s in src)
{
  index = i % lists.Length; //lists is the List<List<string>>
  lists[index].Add(s);
  i++;
}

Of course, you can only split into 10 or 11 lists if there are at least 10 or 11 items in the original list.

yoozer8
  • 7,361
  • 7
  • 58
  • 93
0

The post below shows a good example for splitting arrays:

C# Splitting An Array

It contains both custom split and midpoint split.

Community
  • 1
  • 1
malkassem
  • 1,937
  • 1
  • 20
  • 39
0

This would work for arranging them in groups in sequential order (i.e. {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}, {13, 14}, {15, 16}, {17, 18}, {19, 20}, {21}):

    int groupSize = items.Length / 10;
    string[][] sets = items.Select((str, idx) => new { index = idx, value = str })
                           .GroupBy(a => a.index / groupSize)
                           .Select(gr => gr.Select(n => n.value).ToArray())
                           .ToArray();

If you had 102 items, this would give you 10 arrays of 10 items, and one array of 2 items (the remainder). Is this what you're expecting?

JLRishe
  • 99,490
  • 19
  • 131
  • 169
0

Using MoreLinq's Batch extension method:

private String[][] SplitIntoParts(string[] items, int equalPartsCount)
{
   var batches = items.Batch(items.Count() / equalPartsCount);
   return batches.Select(x => x.ToArray()).ToArray();
}
Meta-Knight
  • 17,626
  • 1
  • 48
  • 58