Array of an unknown length in C# - c#

I've just started learning C# and in the introduction to arrays they showed how to establish a variable as an array but is seems that one must specify the length of the array at assignment, so what if I don't know the length of the array?

Arrays must be assigned a length. To allow for any number of elements, use the List class.
For example:
List<int> myInts = new List<int>();
myInts.Add(5);
myInts.Add(10);
myInts.Add(11);
myInts.Count // = 3

Use List<> to build up an 'array' of unknown length.
Use List<>.ToArray() to return a real array, and not a List.
var list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
var array = list.ToArray();

A little background information:
As said, if you want to have a dynamic collection of things, use a List<T>. Internally, a List uses an array for storage too. That array has a fixed size just like any other array. Once an array is declared as having a size, it doesn't change. When you add an item to a List, it's added to the array. Initially, the List starts out with an array that I believe has a length of 16. When you try to add the 17th item to the List, what happens is that a new array is allocated, that's (I think) twice the size of the old one, so 32 items. Then the content of the old array is copied into the new array. So while a List may appear dynamic to the outside observer, internally it has to comply to the rules as well.
And as you might have guessed, the copying and allocation of the arrays isn't free so one should aim to have as few of those as possible and to do that you can specify (in the constructor of List) an initial size of the array, which in a perfect scenario is just big enough to hold everything you want. However, this is micro-optimization and it's unlikely it will ever matter to you, but it's always nice to know what you're actually doing.

You can create an array with the size set to a variable, i.e.
int size = 50;
string[] words = new string[size]; // contains 50 strings
However, that size can't change later on, if you decide you need 100 words. If you need the size to be really dynamic, you'll need to use a different sort of data structure. Try List.

Use an ArrayList if in .NET 1.x, or a List<yourtype> if in .NET 2.0 or 3.x.
Search for them in System.Collections and System.Collections.Generics.

You might also want to look into Dictionarys if your data is unique, This will give you two columns to work with.
User name , Total bill
it gives you a lot of built in tools to search and update just the value.

var yummy = new List<string>();
while(person.FeelsHappy()) {
yummy.Add(person.GetNewFavoriteFood());
}
Console.WriteLine("Sweet! I have a list of size {0}.", list.Count);
Console.WriteLine("I didn't even need to know how big to make it " +
"until I finished making it!");

try a generic list instead of array

In a nutshell, please use Collections and Generics.
It's a must for any C# developer, it's worth spending time to learn :)

As detailed above, the generic List<> is the best way of doing it.
If you're stuck in .NET 1.*, then you will have to use the ArrayList class instead. This does not have compile-time type checking and you also have to add casting - messy.
Successive versions have also implemented various variations - including thread safe variants.

If you really need to use an array instead of a list, then you can create an array whose size is calculated at run time like so...
e.g i want a two dimensional array of size n by n. n will be gotten at run time from the user
int n = 0;
bool isInteger = int.TryParse(Console.ReadLine(), out n);
var x = new int[n,n];

Related

Sizing a List and referencing variable positions in a List C#

Needed to store many varbiables and at first went with an array, but I had errors when I tried to resize the amount of positions in an array with a separate variabe. Looked online and people said, better use a List.
I have but very confusing to use. Trying to use it logically but I'm just not getting it.
So I set up my list:
public List<int> TESTValues = new List<int>(10);
And to me logically, there should be a list on 10 positions but there isn't, it's empty. Only does it add a variable if I use: TESTValues.Add(1); which only adds 1 new variable in the next available position which is 1 when it should be position 11 right?
Let's say I would somehow get a list of 10 variables, how would I then reference a variable in position 8 of the list, even update it? I tried to use something like: TESTValues.IndexOf(8) = 40; sadly that does not work.
Anyone have a good understanding of these Lists and how I could get to use them? Explain them? Was expecting a List to be simpley than an Array, seems the other way round right now.
Capacity != Size (Count)
Gets or sets the total number of elements the internal data structure can hold without resizing.
The initial capacity given to the constructor has only one purpose: Immediate allocation.
Usually by default a List<T> starts with an initial capacity of 4. Under the hood it simply stores the values in an array.
Then every time you add elements and the new size would exceed the capacity then the underlying array is copied into a new array with double of the original size (= capacity of the list).
The "size" (= Count of the list) only grows by adding elements!
Gets the number of elements contained in the List<T>.
Now the only way to initialize a list with already 10 elements is by using another collection like e.g.
var yourList = new List<int>(new int[10]);
of course this requires the allocation of an array => work for the GC but if you do this only once probably not very problematic.
or using Linq you could also do
using System.Linq;
...
var yourList = Enumerable.Repeat(0, 10).ToList();

"I i can traverse a list using indexing as i do in an array.Why can't i add an item in a list as i do in an array using indexing."

Why do I need to use the Add() to add elements to a List. Why can't I use indexing and do it. When I traverse the elements through the List I do it using the help of indexes.
int head = -1;
List<char> arr = new List<char>();
public void push(char s)
{
++head;
arr[head] = s;//throws runtime error.
arr.Add(s);
}
It doesn't throw any error during compile time. But throws an error at runtime stating IndexOutOfRangeException.
++head;
arr[head] = s;
This attempts to set element 1 of the list to s, but there is no element 1 yet because you've not added anything, or set the length of the list.
When you create an array, you define a length, so each item has a memory address that can be assigned to.
Lists are useful when you don't know how many items you're going to have, or what their index is going to be.
Arrays are fixed sizes. Once you allocate them, you can not add or remove "slots" from it. So if you need it to be bigger, you need to:
Detect that you need a bigger array.
Allocate a new, bigger array
copy all existing values to teh new, bigger array
start using the bigger array from now on everywhere
All that Lists do is automate that precise process. It will automatically detect that it needs to increase during Add() and then do step 2-4 automagically. It is even responsible to pick the initial size and by how much to grow it (to avoid having to grow to often.
They could in theory jsut react to List[11000] by growing the size to 11000. But chances are very big, that this value is a huge mistake. And preventing the Progarmmer from doing huge mistakes is what half the classes and compiler rules (like strong typisation) are there for. So they force you to use Add() so such a mistake can not happen.
Actually calling myArray[2] does not add the element, but just assigns the object to the specified index within the array. If the array´s size is less you´d get an IndexOutOfBoundsException, as in a list<T> also. So also in case of an array using the indexer assumes you actually have that many elements:
var array = new int[3];
array[5] = 4; // bang
This is because arrays have a fixed size which you can´t change. If you assign an object to an index greater the arrays size you get the exat same exception as for a List<T> also, there´s no difference here.
The only real difference here is that when using new array[3] you have an array of size 3 with indices up to 2 and you can call array[2]. However this would just return the default-value - in case of int this is zero. When using new List<int>(3) in contrast you don´t have actually three elements. In fact the list has no items at all and calling list[2] throws the exception. The parameter to a list is just the capacity, which is a parameter for the runtime to indicate when the underlying array of a list should be resized - an ability your array does not even have.
A list is an array wrapper, where the internal array size is managed by its methods. The constructor that takes a capacity simply creates an array of that size internally, but the count property (which reflects the count elements that has been added) will be zero. So in essence, zero slots in the array has been assigned a value.
The size of an array is managed by you the programmer. That is why you have to call static methods like System.Array.Resize (notice that the array argument is ref), if you want to change an array yourself. That method allocates a new chunk of memory for the new size.
So to sum up, the list essentially manages an array for you, and as such, the tradeoff is that you can only access as many array-like slots as has been added to it.

How to create an array without knowing how many values will be store?

In C# I'm storing values in an array.
So to create this array I'm using this code, 'int[] values = new int[10];'
But, what if I need more than 10 values, or in the case I never know how many values I will have. Could be 1, 10 or 100.
I understand the idea that I need to let the compiler know how big the array should be so it can allocate memory space for it.
Is there a way to work around that?
You could just use a List and let it do all the heavy lifting for you:
List<int> values = new List<int>();
Arrays must have defined length. If you want dynamic size, consider using List class.
Please take a look at and research the concept of "Immutable objects"
An array has a fixed size, If you need an array with a dynamic size it is best to either create extension methods or a handler that does the work for you.
The work to be done is to get the array, create a new array with the new size based on whether you want to add or remove something, and to populate the new array with the data from the previous array. This will create a new object instead of modifying the previous object and will make sure you don't push items to a full array, or have an array with a size larger than the items that fit in it.
Ofcourse the List class would work as well and would probably solve your problem.

How to Jagged List C#

I am trying to create a jagged array but due to the dynamic-ness of the data I am working with I do not want to waste resources creating a a large jagged array.
I am currently doing:
int[][][] data = new data[Int16.MaxValue][][];
I do not how big the data set is, or is there a better way than doing it via Lists?
Yes, you should use List<T>.
In this case, you would use List<List<List<int>>>.
Your array:
int[][][] data = new data[Int16.MaxValue][Int16.MaxValue][Int16.MaxValue];
will take up (2^16)^3 = 2^48 = way more storage space than you have,
not to mention that that declaration is not valid C#.
If you don't know how much space you need when you initialize, then it would be best to use a dynamically resizing list.
Use a variable similar to this:
List<List<List<int>>> data = new List<List<List<int>>>();
This variable allows you to add List<List<int>>'s to it, and those lists contain List<int>'s, which of course contain int's
If you absolutely do not want to use Lists, you can always replicate what Lists do under the hood: Create your array with a small number of elements, and when you reach the maximum, create a new array that is double the original's size, copy your existing array into it, and dispose of your original. Continue this pattern until you are done. I recommend using Lists instead, but this is how you would get around it if, for some reason, you just don't want to use Lists.
In fact, you can create jagged arrays without defining second and further dimensions.
int[][][] jagged = new int[256][][];
But at large datasets it is more effective to use streaming data - i.e., combinations of IEnumerable<T>.

C# linked lists

very basic question, but is there any ToArray-like function for c# linked lists that would return an array of only part of the elements in the linkedlist.
e.g.: let's say my list has 50 items and I need an array of only the first 20. I really want to avoid for loops.
Thanks,
PM
Use Linq?
myLinkedList.Take(20).ToArray()
or
myLinkedList.Skip(5).Take(20).ToArray()
You say you "really want to avoid for loops" - why?
If you're using .NET 3.5 (or have LINQBridge), it's really easy:
var array = list.Take(20).ToArray();
... but obviously that will have to loop internally.
Note that this will create a smaller array if the original linked list has fewer than 20 elements. It's unclear whether or not that's what you want.
Something is going to have to loop internally, sooner or later - it's not like there's going to be a dedicated CPU instruction for "navigate this linked list and copy a fixed number of pointers into a new array". So the question is really whether you do it or a library method.
If you can't use LINQ, it's pretty easy to write the equivalent code yourself:
int size = Math.Min(list.Count, 20);
MyType[] array = new MyType[size];
var node = list.First;
for (int i = 0; i < size; i++)
{
array[i] = node.Value;
node = node.Next;
}
That will actually be slightly more efficient than the LINQ approach, too, because it creates the array to be exactly the right size to start with. Yes, it uses a loop - but as I say, something's got to.
If you're using the LinkedList collection class (from System.Collections.Generic), you can use LINQ to get it:
var myArray = list.Take(20).ToArray();

Categories

Resources