I would use Linq to solve the problem. (Be sure you have using System.Linq;
at the top of your code file!)
First of all, we define a function to break down an object into several strings with length 5 or less or the object itself, if it is not a string.
object[] BreakDownObject(object o)
=> BreakDownObjectToEnumerable(o).ToArray();
IEnmuerable<object> BreakDownObjectToEnumerable(object o)
{
// If object is string, thant yield return every part
// with 5 characters (or less than 5, if necessary,
// for the last one)
if(o is string s)
{
for(int i = 0; i < s.Length; i += maxStringLength)
{
yield return s.Substring(i, Math.Min(s.Length - i, maxStringLength));
}
}
// object is not a string, don't break it up
else
{
yield return o;
}
}
Wie use Substring in Combination with Math.Min
. If length - index
is smaller than 5, than we use this instead for the substring.
If we use this function on all items of the list we get an array of arrays of object. This array could be interpreted as "columns", because the first index gives us the columns, and the second index the subsequent broken down strings.
var data = new List<object> { "ABCDEFGHIJKLMNO", 80, "TestMain", "PQRSTUVWXY" };
object[][] columns = data.Select(BreakDownObject).ToArray();
Now we want to transpose the array, so rows first. We write a function, that takes an index and our array of arrays and returns the row with that index. (Again I use Linq-IEnumerable for easier creation of the array):
object[] GetRowAtIndex(int index, object[][] columns)
=> GetRowAtIndexAsEnumerable(index, columns).ToArray();
IEnumerable<object> GetRowAtIndexAsEnumerable(int index, object[][] columns)
{
foreach(var column in columns)
{
// Each column has different length,
// if index is less than length, we
// return the item at that index
if(index < column.Length)
{
yield return column[index];
}
// If index is greater or equal length
// we return a string with a single space
// instead.
else
{
yield return " ";
}
}
}
This function also fills up missing items in the columns with a one-space string.
Last but not least, we iterate through the rows, until no column has items left:
List<object[]> GetAllRows(object[][] columns)
=> GetAllRowsAsEnumerable(columns);
Enumerable<object[]> GetAllRowsAsEnumerable(object[][] columns)
{
int index = 0;
while(true)
{
// Check if any column has items left
if(!columns.Any(column => index < column.Length))
{
// No column with items left, left the loop!
yield break;
}
// return the row at index
yield return GetRowAtIndex(index, columns);
// Increase index
++index;
}
}
Put it together as one function:
List<object[]> BreakDownData(List<object> data)
{
object[][] columns = data.Select(BreakDownObject).ToArray();
return GetAllRows(columns);
}
After that, your code would be:
var data = new List<object> { "ABCDEFGHIJKLMNO", 80, "TestMain", "PQRSTUVWXY" };
var new_data = BreakDownData(data);