Best way to handle array of arrays in C# - c#

I need to create an array of string arrays in C#. Basically, I want to do the following, kind of a hybrid C/C#:
private string[] revA = new string[] {"one", "two", "three" };
private string[] revB = new string[] {"four", "five", "six" };
private string[] revC = new string[] {"seven", "eight", "nine" };
string[,] list = {revA, revB, revC};
string outStr = list[0][0]; // outStr == "one"
string outStr = list[2][1]; // outStr == "eight"
But I know that won't work.
I've looked into ArrayList and List, but I'm not sure how to make it work.
Any help would be appreciated.

You need to use Jagged Array string[][] instead of Multidimensional Array string[,]
This source can give you more detail about it Why we have both jagged array and multidimensional array?

string[,] list = new string[3, 3] {{"one", "two", "three" },
{"four", "five", "six" },
{"seven", "eight", "nine" } };
string outStr = list[0, 0]; // outStr == "one"

This can be possible with ArrayList and with List in C#.
I tried the following code you can check and explore more according to your requirements.
string[] reva = new string[] { "one", "two", "three" };
string[] revb = new string[] { "four", "five", "six" };
string[] revc = new string[] { "seven", "eight", "nine" };
ArrayList arrayList = new ArrayList() { reva, revb, revc };
List<string> nums = reva.Cast<string>().ToList();
nums.ForEach(Console.WriteLine);
Console.ReadLine();
Console.ReadLine();

While jagged and multidimensional arrays have been mentioned, a third option is a custom multidimensional array type. Something like
public class My2DArray<T>
{
public T[] Array { get; }
public int Width { get; }
public int Height { get; }
public My2DArray(int width, int height, params T[] initialItems)
{
Width = width;
Height = height;
Array = new T[width * height];
initialItems.CopyTo(Array, 0);
}
public T this[int x, int y]
{
get => Array[y * Width + x];
set => Array[y * Width + x] = value;
}
}
This has the advantage over multidimensional array in that the backing single dimensional array is directly accessible, and this can be good for interoperability, or if you just want to iterate over all items.
You can add constructors to initialize it however you want.

Related

How do I sort numbers written in string format("one "two" three" etc.) according to their value using LINQ C# lambda expressions

public static IEnumerable<string> OrderingReversal()
{
string[] digits = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
var res = digits.Where(w => w[1] == 'i')
.OrderByDescending(w => Convert.ToInt32(w)).ToList<string>();
return res;
}
I would like the output to be: "nine", "eight", "six" and "five"
I tried to achieve this by the code I provided above.
However, I am receiving runtime error:
System.FormatException: 'Input string was not in a correct format.'
Any Help would be appreciated.
Thank you!
A big part of the solution is found in other answers like this one but more is needed to sort the results.
Here's a class that will take a list of strings and return them sorted by the numeric values they represent:
public delegate long ConvertStringToNumberDelegate(string number);
public class NumbersAsTextSorter
{
private readonly ConvertStringToNumberDelegate _convertStringToNumberFunction;
public NumbersAsTextSorter(ConvertStringToNumberDelegate convertStringToNumberFunction)
{
_convertStringToNumberFunction = convertStringToNumberFunction;
}
public IEnumerable<string> ReverseSort(IEnumerable<string> input)
{
var textWithNumbers = input.Select(i => new {input = i, value = _convertStringToNumberFunction(i)});
return textWithNumbers.OrderByDescending(t => t.value).Select(s => s.input);
}
}
This will create a collection of text inputs matched with numeric values. It sorts the collection by the numeric value and then returns the text inputs in that sorted order.
As you can see, a critical detail is missing. How do you convert "one" to 1, "two" to 2, and so forth?
For that you need an implementation of the delegate - ConvertStringToNumberDelegate. You can get that by using the class in the the answer I referenced above.
For convenience I've copied that static method (for which I am explicitly not taking credit!) into a static class:
public static class TestToNumbers
{
private static Dictionary<string, long> numberTable =
new Dictionary<string, long>
{{"zero",0},{"one",1},{"two",2},{"three",3},{"four",4},
{"five",5},{"six",6},{"seven",7},{"eight",8},{"nine",9},
{"ten",10},{"eleven",11},{"twelve",12},{"thirteen",13},
{"fourteen",14},{"fifteen",15},{"sixteen",16},
{"seventeen",17},{"eighteen",18},{"nineteen",19},{"twenty",20},
{"thirty",30},{"forty",40},{"fifty",50},{"sixty",60},
{"seventy",70},{"eighty",80},{"ninety",90},{"hundred",100},
{"thousand",1000},{"million",1000000},{"billion",1000000000},
{"trillion",1000000000000},{"quadrillion",1000000000000000},
{"quintillion",1000000000000000000}};
public static long ToLong(string numberString)
{
var numbers = Regex.Matches(numberString, #"\w+").Cast<Match>()
.Select(m => m.Value.ToLowerInvariant())
.Where(v => numberTable.ContainsKey(v))
.Select(v => numberTable[v]);
long acc = 0, total = 0L;
foreach (var n in numbers)
{
if (n >= 1000)
{
total += (acc * n);
acc = 0;
}
else if (n >= 100)
{
acc *= n;
}
else acc += n;
}
return (total + acc) * (numberString.StartsWith("minus",
StringComparison.InvariantCultureIgnoreCase) ? -1 : 1);
}
}
Now you can create an instance of NumbersAsTextSorter which uses that static method to convert text to numbers. I've done that in this unit test which passes:
[TestMethod]
public void TestSorting()
{
var sorter = new NumbersAsTextSorter(TestToNumbers.ToLong);
var output = sorter.ReverseSort(new string[] { "one", "three hundred", "zero" });
Assert.IsTrue(output.SequenceEqual(new string[] { "three hundred", "one", "zero" }));
}
For clarity, this is passing in "one", "three hundred", and "zero" and asserting that after it's sorted, the sequence is "three hundred", "one", "zero".
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string[] digits = { "Zero", "one", "two", "Three", "four", "five", "Six", "seven", "eight", "nine" };
var asc = OrderNumberStringsByValue(digits);
var dec = OrderNumberStringsByValue(digits, true);
string[] myDigits = { "Eight", "nine", "Five", "six" };
var myAsc = OrderNumberStringsByValue(myDigits);
var myDec = OrderNumberStringsByValue(myDigits, true);
Console.WriteLine($"asc: {string.Join(", ", asc)}");
Console.WriteLine($"dec: {string.Join(", ", dec)}");
Console.WriteLine($"myAsc: {string.Join(", ", myAsc)}");
Console.WriteLine($"myDec: {string.Join(", ", myDec)}");
Console.ReadLine();
}
public static IEnumerable<string> OrderNumberStringsByValue(IEnumerable<string> numbers, bool decending = false)
{
return numbers.OrderBy(n => (decending ? -1 : 1) * (int)Enum.Parse(typeof(Numbers), n.ToLower()));
}
}
enum Numbers : int
{
zero = 0,
one = 1,
two = 2,
three = 3,
four = 4,
five = 5,
six = 6,
seven = 7,
eight = 8,
nine = 9
}
}

Adding array to Jagged Array c#

I've had a look at both ASP.Net c# adding items to jagged array and vb.net assign array to jagged array but I just can't seem to work this out...
So, essentially, it's this. I have a function that builds a list of values from a query or two. I'm adding each value returned to a list then converting the list to an array. All is good
However, I now need to return two values, so a multi dimension array appears more suitable. Essentially, this is what I want to do:
string[][] array2D = new string[2][];
array2D[0] = new string[3] { "one", "two", "three" };
array2D[1] = new string[3] { "abc", "def", "ghi" };
All good so far. However, I don't know the values that I want to plug in to the array at the time of array initialisation, so, this is what I'd expect to be able to do:
string[][] array2D = new string[2][];
//array2D[0] = new string[3] { "one", "two", "three" };
//array2D[1] = new string[3] { "abc", "def", "ghi" };
string[] deviceIDS = { "one", "two", "three" };
string[] groupIDS = { "abc", "def", "ghi" };
array2D[0] = new string[deviceIDS.Length] deviceIDS;
array2D[1] = new string[deviceIDS.Length] groupIDS;
But it really doesn't like the last two lines, report it needs a ;
You have already created arrays here:
string[] deviceIDS = { "one", "two", "three" };
string[] groupIDS = { "abc", "def", "ghi" };
So you only need to set references to these arrays:
array2D[0] = deviceIDS;
array2D[1] = groupIDS;

Splitting an array into 2 arrays C#

Edit: I have tried the Take/Skip method but I get the following error:
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<string>' to
'string[]'. An explicit conversion exists (are you missing a cast?)
I do not know what I am doing wrong because I copied Saeed's code.
I have a string array (containing anywhere from 20 to 300 items) and I want to split it into 2 separate arrays, from the middle of the first one.
I know how I can do this using a for loop but I would like to know if there was a faster/better way of doing it. I also need to be able to correctly split an array even if it has an odd number of items, eg:
string[] words = {"apple", "orange", "banana", "pear", "lemon"};
string[] firstarray, secondarray;
SplitArray(words, out firstarray, out secondarray); // Or some other function
// firstarray has the first 3 of the items from words, 'apple', 'orange' and 'banana'
// secondarray has the other 2, 'pear' and 'lemon'
You can use linq:
firstArray = array.Take(array.Length / 2).ToArray();
secondArray = array.Skip(array.Length / 2).ToArray();
Why this works, despite the parity of the original array size?
The firstArray takes array.Length / 2 elements, and the second one skips the first array.Length / 2 elements, it means there isn't any conflict between these two arrays. Of course if the number of elements is odd we cannot split the array into two equal size parts.
If you want to have more elements in the first half (in the odd case), do this:
firstArray = array.Take((array.Length + 1) / 2).ToArray();
secondArray = array.Skip((array.Length + 1) / 2).ToArray();
string[] words = {"apple", "orange", "banana", "pear", "lemon"};
int mid = words.Length/2;
string[] first = words.Take(mid).ToArray();
string[] second = words.Skip(mid).ToArray();
If you don't want to/can't use LINQ you can simply do:
string[] words = { "apple", "orange", "banana", "pear", "lemon" };
string[] firstarray, secondarray;
int mid = words.Length / 2;
firstarray = new string[mid];
secondarray = new string[words.Length - mid];
Array.Copy(words, 0, firstarray, 0, mid);
Array.Copy(words, mid, secondarray, 0, secondarray.Length);
A more generalized approach that will split it into as many parts as you specify:
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> list, int parts)
{
return list.Select((item, index) => new {index, item})
.GroupBy(x => (x.index + 1) / (list.Count()/parts) + 1)
.Select(x => x.Select(y => y.item));
}
*Edited Thanks skarmats
string[] words = { "apple", "orange", "banana", "pear", "lemon" };
var halfWay = words.Length/2;
var firstHalf = words.Take(halfWay);
var secondHalf = words.Skip(halfWay);
You can achive that quite easily using range notation:
var x = new[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
var pivot = x.Length / 2;
var p1 = x[..pivot];
var p2 = x[pivot..];
Just in case someone wants to use a function instead:
static void Main(string[] args)
{
string[] ar = { "apple", "orange", "banana", "pear", "lemon" };
int half = ar.Length / 2;
// Console.WriteLine(string.Join(',', Split(ar,0, half)));
Console.WriteLine(string.Join(',', Split(ar,half, ar.Length)));
Console.ReadKey();
}
public static IEnumerable<T> Split<T>(IEnumerable<T> items, int start, int end)
{
return items.Skip(start).Take(end);
}

How can I initialize a C# List in the same line I declare it. (IEnumerable string Collection Example)

I am writing my testcode and I do not want wo write:
List<string> nameslist = new List<string>();
nameslist.Add("one");
nameslist.Add("two");
nameslist.Add("three");
I would love to write
List<string> nameslist = new List<string>({"one", "two", "three"});
However {"one", "two", "three"} is not an "IEnumerable string Collection". How can I initialise this in one line using the IEnumerable string Collection"?
var list = new List<string> { "One", "Two", "Three" };
Essentially the syntax is:
new List<Type> { Instance1, Instance2, Instance3 };
Which is translated by the compiler as
List<string> list = new List<string>();
list.Add("One");
list.Add("Two");
list.Add("Three");
Change the code to
List<string> nameslist = new List<string> {"one", "two", "three"};
or
List<string> nameslist = new List<string>(new[] {"one", "two", "three"});
Just lose the parenthesis:
var nameslist = new List<string> { "one", "two", "three" };
Posting this answer for folks wanting to initialize list with POCOs and also coz this is the first thing that pops up in search but all answers only for list of type string.
You can do this two ways one is directly setting the property by setter assignment or much cleaner by creating a constructor that takes in params and sets the properties.
class MObject {
public int Code { get; set; }
public string Org { get; set; }
}
List<MObject> theList = new List<MObject> { new MObject{ PASCode = 111, Org="Oracle" }, new MObject{ PASCode = 444, Org="MS"} };
OR by parameterized constructor
class MObject {
public MObject(int code, string org)
{
Code = code;
Org = org;
}
public int Code { get; set; }
public string Org { get; set; }
}
List<MObject> theList = new List<MObject> {new MObject( 111, "Oracle" ), new MObject(222,"SAP")};
This is one way.
List<int> list = new List<int>{ 1, 2, 3, 4, 5 };
This is another way.
List<int> list2 = new List<int>();
list2.Add(1);
list2.Add(2);
Same goes with strings.
Eg:
List<string> list3 = new List<string> { "Hello", "World" };
List<string> nameslist = new List<string> {"one", "two", "three"} ?
Remove the parentheses:
List<string> nameslist = new List<string> {"one", "two", "three"};
It depends which version of C# you're using, from version 3.0 onwards you can use...
List<string> nameslist = new List<string> { "one", "two", "three" };
I think this will work for int, long and string values.
List<int> list = new List<int>(new int[]{ 2, 3, 7 });
var animals = new List<string>() { "bird", "dog" };

How can I declare a two dimensional string array?

string[][] Tablero = new string[3][3];
I need to have a 3x3 array arrangement to save information to. How do I declare this in C#?
string[,] Tablero = new string[3,3];
You can also instantiate it in the same line with array initializer syntax as follows:
string[,] Tablero = new string[3, 3] {{"a","b","c"},
{"d","e","f"},
{"g","h","i"} };
You probably want this:
string[,] Tablero = new string[3,3];
This will create you a matrix-like array where all rows have the same length.
The array in your sample is a so-called jagged array, i.e. an array of arrays where the elements can be of different size. A jagged array would have to be created in a different way:
string[][] Tablero = new string[3][];
for (int i = 0; i < Tablero.GetLength(0); i++)
{
Tablero[i] = new string[3];
}
You can also use initializers to fill the array elements with data:
string[,] Tablero = new string[,]
{
{"1.1", "1.2", "1.3"},
{"2.1", "2.2", "2.3"},
{"3.1", "3.2", "3.3"}
};
And in case of a jagged array:
string[][] Tablero = new string[][]
{
new string[] {"1.1", "1.2"},
new string[] {"2.1", "2.2", "2.3", "2.4"},
new string[] {"3.1", "3.2", "3.3"}
};
You just declared a jagged array. Such kind of arrays can have different sizes for all dimensions. For example:
string[][] jaggedStrings = {
new string[] {"x","y","z"},
new string[] {"x","y"},
new string[] {"x"}
};
In your case you need regular array. See answers above.
More about jagged arrays
I assume you're looking for this:
string[,] Tablero = new string[3,3];
The syntax for a jagged array is:
string[][] Tablero = new string[3][];
for (int ix = 0; ix < 3; ++ix) {
Tablero[ix] = new string[3];
}
There are 2 types of multidimensional arrays in C#, called Multidimensional and Jagged.
For multidimensional you can by:
string[,] multi = new string[3, 3];
For jagged array you have to write a bit more code:
string[][] jagged = new string[3][];
for (int i = 0; i < jagged.Length; i++)
{
jagged[i] = new string[3];
}
In short jagged array is both faster and has intuitive syntax. For more information see: this Stackoverflow question
try this :
string[,] myArray = new string[3,3];
have a look on http://msdn.microsoft.com/en-us/library/2yd9wwz4.aspx
string[,] Tablero = new string[3,3];
string[][] is not a two-dimensional array, it's an array of arrays (a jagged array). That's something different.
To declare a two-dimensional array, use this syntax:
string[,] tablero = new string[3, 3];
If you really want a jagged array, you need to initialize it like this:
string[][] tablero = new string[][] { new string[3],
new string[3],
new string[3] };
A 3x3 (multidimensional) array can also be initialized (you have already declared it) like this:
string[,] Tablero = {
{ "a", "b", "c" },
{ "d", "e", "f" },
{ "g", "h", "i"}
};
When you are trying to create a multi-dimensional array all you need to do is add a comma to the declaration like so:
string[,] tablero = new string[3,3].
you can also write the code below.
Array lbl_array = Array.CreateInstance(typeof(string), i, j);
where 'i' is the number of rows and 'j' is the number of columns.
using the 'typeof(..)' method you can choose the type of your array i.e. int, string, double
There are many examples on working with arrays in C# here.
I hope this helps.
Thanks,
Damian

Categories

Resources