C# Multidimensional array with string[] and string - c#

I basically want to make an array which contains one string[] and one normal string.
onion / {strawberry, banana, grape} in one array.
string[,] foodArray = new string[,] { onion, { strawberry, banana, grape } }
I'm wondering if it's even possible...
Thank you.

This sort of data typing is unclear for what you want to do. Use your types to clearly communicate your intentions
If you plan to lookup by the first string, I might recommend Dictionary<string, List<string>>. The Dictionary collection is an extremely useful collection type
If you want strictly arrays then you must use a jagged array as this will allow you to constrain the first "column" to being only 1 length while the list (2nd column) may be variable length. This would mean string[][] foodArray = new string[1][];
In either case multidimensionals arrays are not suited here, it will lead to wasted space as it allocates all the cells for the dimensions you set. Rule of thumb, always prefer jagged over multidimensional arrays unless you are absolutely sure the entire multidimensional array will be filled to its max in all its dimensions.

I think you do not really want a two dimensional array in this case.
What you really want is an array of a tuple.
using System;
namespace tuple_array
{
using Item = Tuple<String,String[]>;
class Program
{
static void Main(string[] args)
{
Item[] foodarray = new Item[] {
new Item("onion", new string[]
{ "strawberry", "banana", "grape" })
};
foreach (var item in foodarray) {
var (f,fs) = item;
var foo = string.Join(",", fs);
Console.WriteLine($"[{f},[{foo}]]");
}
}
}
}
It looks somewhat clumsy in C#, the F# version is much more terse and pretty:
type A = (string * string []) []
let a : A = [| "onion", [| "strawberry"; "banana"; "grape" |] |]
printfn "%A" a

Related

Array.Sort() sorts original array and not just copy

This code snippet is from C# 2010 for Dummies. What confuses me is that when using the Array.Sort() method, both my copy of the array (sortedNames) and the original array (planets) get sorted, even though it only calls the Sort method on sortedNames.
It doesn't matter which array the second foreach loop references, the output is the same.
static void Main(string[] args)
{
Console.WriteLine("The 5 planets closest to the sun, in order: ");
string[] planets = new string[] { "Mercury","Venus", "Earth", "Mars", "Jupiter"};
foreach (string planet in planets)
{
Console.WriteLine("\t" + planet);
}
Console.WriteLine("\nNow listed alphabetically: ");
string[] sortedNames = planets;
Array.Sort(sortedNames);
foreach (string planet in planets)
{
Console.WriteLine("\t" + planet);
}
}
Both sortedNames and planets refer to the same array. Basically both variables point to the same location in memory, so when you call Array.Sort on either variable, the changes to the array are reflected by both variables.
Since arrays in C# are reference types, both sortedNames and planets "point" to the same location in memory.
Contrast this with value types, which hold data within their own memory allocation, instead of pointing to another location in memory.
If you wanted to keep planets intact, you could use create a brand new array, then use Array.Copy to fill the new array with the contents of planets:
/* Create a new array that's the same length as the one "planets" points to */
string[] sortedNames = new string[planets.Length];
/* Copy the elements of `planets` into `sortedNames` */
Array.Copy(planets, sortedNames, planets.Length);
/* Sort the new array instead of `planets` */
Array.Sort(sortedNames);
Or, using LINQ you could use OrderBy and ToArray to create a new, ordered array:
string[] sortedNames = planets.OrderBy(planet => planet).ToArray();
Some resources that might help with value types and reference types:
Value types and Reference Types (MSDN)
What is the difference between a reference type and value type in c#?
Alternatively you could use Array.Clone to avoid having to first create a new array. Then sort.
string[] sortedNames = (string[]) Array.Clone(planets);
Array.Sort(sortedNames);
See also this other discussion Difference between the System.Array.CopyTo() and System.Array.Clone()

How to create 2 multidimensional string array (remove blank strings)?

var movieNext = new string[,]
{
{ "superhero", "action", "waltdisney", "bat"},
{"superhero", "action", "marvel",""},
{"history", "action", "malay", "" },
{"malay", "novel", "", ""},
{"history", "bat", "", ""}
};
The above code is a multidimensional array, which stores a sequence of movie's keyword. Is there a way to implement this without having to put the blank strings in the array initialization?
For example you can see in the above code, I have to put the blank string "" to fill up the array.
You could use a jagged array instead.
string[][] movieNext = new string[][] { { etc... } }.
You can consider C# jagged array (though they are different from multi-dimensional arrays).
string[][] movieNext = {
new [] { "superhero", "action", "waltdisney", "bat"},
new [] {"superhero", "action", "marvel"}, <and so on>
};
If you want to stick with multi-dimensional arrays, you have to initialize the values individually. If you don't provide any string value for any of the index (i,j) by default it will be null.
I suggest never to use two-dimensional arrays. They have practically no support in the API (you'll be hard pressed to find a method that accepts a two-dimensional array as a parameter), and cannot be cast to IEnumerable<T> or similar well-supported interface. As such, you can really use them only in the most local of scopes.
Instead, I suggest you use something castable to IEnumerable<IEnumerable<string>>. Oh, another tip. Check this out. Specifically,
To initialize a Dictionary, or any collection whose Add method takes multiple parameters, enclose each set of parameters in braces as shown in the following example.
Thus, the following will work:
class Program
{
static void Main(string[] args)
{
var d = new ManyList()
{
{"Hi", "Good", "People", "None", "Other"}
{"Maybe", "Someone", "Else", "Whatever"}
};
Console.Read();
}
}
class ManyList : List<string>
{
public void Add(params string[] strs)
{
Console.WriteLine(string.Join(", ", strs));
}
}
This might help you clean up your syntax a bit.

Multidimensional List C#

I need to create a multidimensional guard List three values​​, X, Y and Z, and I need a List that is because once the value is queried, the array must be removed.
The query would look something like this: List [0] [0] = X, List [0] [a] = Y and List [0] [2] = X, so that I can remove only the index 0 and he already remove all the other three.
If you need to create a multidimensional list, you can always create a list of lists like so:
var multiDimensionalList = new List<List<string>>{
new List<string>{"A","B","C"},
new List<string>{"D","E","F"},
new List<string>{"G","H","I"},
};
Console.WriteLine(multiDimensionalList[2][1]); // Prints H
multiDimensionalList[2].RemoveAt(1);
Console.WriteLine(multiDimensionalList[2][1]); // Prints I
multiDimensionalList[2][1] = "Q";
Console.WriteLine(multiDimensionalList[2][1]); // Prints Q
Be aware though that attempting to replace a value that doesn't exist by way of assignment will throw an exception:
multiDimensionalList[2][5] = "R"; // Throws an ArgumentOutOfRangeException
Your question is very hard to understand, but perhaps what you are looking for can be accomplished with an array of arrays? This is how multidimensional arrays are implemented in some languages anyways.
In your case you might be using a List of List's: List>. And this would satisfy your requirement to remove "all the other three" by removing the first element in the outer List<> object.
I'm sorry but your question is a little bit hard to understand, but I will take a stab at it. Please don't interchange the words Array and List as they are different yet related ideas in C#. I believe that you mean Array with your use of [] brackets. Although you might want to consider using lists as they have a nice way to remove certain elements from a list by using the element. the MSDN has some good information as to how you might proceed.
List(T).Remove method
the list will restructure it self to remove or add elements as desired.
I am not sure I am following your logic as you are using both strings and integers as your second indexer, and referencing X twice, but not Z. Assuming these are typos, I am going to take a guess at what you want.
Have you considered a custom type with X, Y, AND Z properties, and an indexer to give you the behavior you described:
You also don't mention what types your values are, so I am using object, but feel free to substitute your own type (or a generic type)
public class MyType
{
private object[] backingArray = new object[3];
public object this[int index]
{
get { return backingArray[index]; }
set { backingArray[index] = value; }
}
public object X
{
get { return backingArray[0]; }
set { backingArray[0] = value; }
}
public object Y
{
get { return backingArray[1]; }
set { backingArray[1] = value; }
}
public object Z
{
get { return backingArray[2]; }
set { backingArray[2] = value; }
}
}
You could then use it like this:
List<MyType> list = new List<MyType>();
list = PopulateList(); // fill list with values
var x = list[0][0];
var y = list[0][1];
var z = list[0][2];
Of course, this implementation depends on your 2nd dimension always consisting of 3 elements. If it will not be consistent, then one of the other answers abound for your needs.

Adding to an Array

I have an array:
String[] ay = {
"blah",
"blah number 2"
"etc" };
... But now I want to add to this array at a later time, but I see no option to do so. How can this be done? I keep getting a message saying that the String cannot be converted to String[].
Thank you
Use a List rather than an array:
List<string> list = new List<string>();
list.Add( "blah" ) ;
Then, later, if you really do need it as an array:
string[] ay = list.ToArray();
Arrays are of fixed size, so after it has been created, you can't change the size of it (without creating a new array object)
Use the List<string> instead of the array.
Arrays can't change their size after they are declared. Use collections instead. For example: List.
As everyone's already said, use List in the System.Collections.Generic namespace.
You could also use a Hashtable which will allow you to give each string a meaning, or "key" which gives you an easy way to pull out a certain string with a keyword. (as for keeping messages stored in memory space for whatever purpose.)
You could also Create a new array each time you add a value, make the new array 1 bigger than the old one, copy all the data from the first array into the 2nd array, and then add your new value in the last slot (Length - 1)
Then replace the old array with your new one.
It's the most manual way of doing it.
But List and Hashtable work perfectly well too.
If you don't need indexing a specific array element (usage of brackets), but you want to be able to efficiently add or remove elements, you could use LinkedList.
If you do need indexing
have a look at Dictionary data type also in the System.Collection
http://msdn.microsoft.com/en-us/library/xfhwa508.aspx
so you could do something like
Dictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Add(1, "afljsd");
You can do this but I don't recommend it:
// Reallocates an array with a new size, and copies the contents
// of the old array to the new array.
// Arguments:
// oldArray the old array, to be reallocated.
// newSize the new array size.
// Returns A new array with the same contents.
public static System.Array ResizeArray (System.Array oldArray, int newSize) {
int oldSize = oldArray.Length;
System.Type elementType = oldArray.GetType().GetElementType();
System.Array newArray = System.Array.CreateInstance(elementType,newSize);
int preserveLength = System.Math.Min(oldSize,newSize);
if (preserveLength > 0)
System.Array.Copy (oldArray,newArray,preserveLength);
return newArray;
}
Here's an extension method to add the to arrays together and create a new string array
public static class StringArrayExtension
{
public static string[] GetStringArray (this string[] currentArray, string[] arrayToAdd)
{
List<String> list = new List<String>(currentArray);
list.AddRange(arrayToAdd);
return list.ToArray();
}
}

Deep copying reference types

I am using a class called BigNumDesc that represents a number. I have a jagged array of that numbers, that represent a matrix.
I first declare this matrix the following way:
BigNumDec[][] matrix = new BigNumDec[][] {
new BigNumDec[] { 1, 2 },
new BigNumDec[] { 3, 4 }
};
Now, I have this method I want to call:
static BigNumDec[][] GetStrictlyUpperTriangle(BigNumDec[][] matrix)
{
BigNumDec[][] newMatrix = new BigNumDec[matrix.Length][];
matrix.CopyTo(newMatrix, 0);
return null;
}
I have a break-point in the last line. If in the watch window, I take any item of matrix, and change it, it will change too newMatrix, as all BigNumDec are reference types(bad design decision from the creator of it?). How can I accomplish this? I need to make modifications to newMatrix, so I must copy it first from matrix.
edit: Tried the same now with ints, but it's happening just the same. I'd it wouldn't happen with value types?
BigNumDec is immutable.
The reason it's still happening with value types is because you're using an array of arrays. You're shallow-copying the "outer" array, which just copies the references to the two "inner" arrays.
You haven't shown whether BigNumDec is immutable or not (I would hope so) but if it is, you should be fine if you just deep copy the array. Alternatively, can you use a rectangular array [,] instead of a jagged array [][]? If so, a simple copy would suffice. There are performance implications with rectangular arrays, mind you - it's worth testing this to see whether it'll be a problem for you. You get better locality of reference, but the actual array access isn't as fast.
The issue is with your initialisation of the BigNumDec array, you are creating a 1-dimensional array of BigNumDec objects. [0] = { 1, 2 }, [1] = { 3. 4 }. You are then effectively copying the references those objects, not their content, hence why the values continue to change.
Change your initialisation to:
BigNumDec[,] matrix = new BigNumDec[,] {
{ 1, 2 },
{ 3, 4 }
};
If your objects are Serializable you can implement deep copy using serialization. It's not very efficient (by performance) but it's simple.
public BigNumDec[][] CopyUsingSerialization(BigNumDec[][] original)
{
var binaryFormatter = new BinaryFormatter();
var serializationStream = new MemoryStream();
binaryFormatter.Serialize(serializationStream, original);
serializationStream.Position = 0;
var copy = (BigNumDec[][])binaryFormatter.Deserialize(serializationStream);
return copy;
}
You have to declare the BigNumDec as [Serializable]:
[Serializable]
public class BigNumDec
{
//class content
}
(as said in other answers here, if you can move to two dimensional array instead of jagged you'll get better solution)

Categories