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
13
  • 2
    Given: _____ Expected: ______ Commented Jan 10, 2013 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 Commented Jan 10, 2013 at 15:23
  • @Ramie: We don't know what requirements you have. What is the expected output of some given input? Commented Jan 10, 2013 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<T, T2>? Commented Jan 10, 2013 at 15:26
  • 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. Commented Jan 10, 2013 at 15:33

6 Answers 6

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)

Sign up to request clarification or add additional context in comments.

2 Comments

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?
The first would get 4 and the second 3 (in my example with two arrays).
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, 

Comments

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.

Comments

0

The post below shows a good example for splitting arrays:

C# Splitting An Array

It contains both custom split and midpoint split.

1 Comment

More of a comment / request for a duplicate link, than an answer.
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?

Comments

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();
}

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.