I am using C#.
I have an array of size 10. I want to pass it to a function, but only from the second element. In C, this is how I would implement it
myfunc( myarray + 1 )
Effectively I am virtually shifting the array / deleting the first element.
How do I implement this in C# ?
If you're using .NET 3.5, the easiest is to use Skip(1) then convert back to an array.
myFunc(myArray.Skip(1).ToArray());
If performance is an issue then you will either need to construct a new array manually or change your function to accept an index parameter.
There are four options here:
Pass in an index, and use that in your function
Make your function use IEnumerable<T> instead of an array (T[]), then use myArray.Skip(1).
Use skip, but convert back to an array. This copies the array elements, however.
Use an ArraySegment<T> instead of an array for your function.
This really depends on whether you have control over the usage within your myfunc function. If that function must accept an array, and you can't pass an index, you're going to be stuck creating a copy of the array.
You could pass an index to the function also, and only access the array beginning at that index.
Related
Will the index an item in a List theList be the same as its index in theList.ToArray()? i.e., does theList[i]==theList.ToArray()[i] for sure? Assuming the answer is yes just want to double check.
Update:
Here is a use case, if you can't imagine this is useful: I am using an optimization routine that accepts an array as input. Currently my variables are in a list. I want to run the optimization routine on the variables, then take the result of the optimization routine (which is an array obviously), and put them back in the list. I want to be sure I can just put them back at their original indices.
ToArray uses Array.Copy under the hood which preserves order.
From Array.Copy
Copies a range of elements from an Array starting at the first element
and pastes them into another Array starting at the first element. The
length is specified as a 32-bit integer.
From ToArray
The elements are copied using Array.Copy, which is an O(n) operation,
where n is Count.
LINQ's ToArray just enumerates the collection and stuffs the results into an array. List<T> enumerates linearly, so yes; the indices will match.
Please note that this is not guaranteed by the .NET specification/documentation, but is unlikely to change.
Is it possible in c# to initialize an array in, for example, subindex 1?
I'm working with Office interop, and every property is an object array that starts in 1 (I assume it was originally programed in VB.NET), and you cannot modify it, you have to set the entire array for it to accept the changes.
As a workaround I am cloning the original array, modifying that one, and setting it as a whole when I'm done.
But, I was wondering if it was possible to create a new non-zero based array
It is possible to do as you request see the code below.
// Construct an array containing ints that has a length of 10 and a lower bound of 1
Array lowerBoundArray = Array.CreateInstance(typeof(int), new int[1] { 10 }, new int[1] { 1 });
// insert 1 into position 1
lowerBoundArray.SetValue(1, 1);
//insert 2 into position 2
lowerBoundArray.SetValue(2, 2);
// IndexOutOfRangeException the lower bound of the array
// is 1 and we are attempting to write into 0
lowerBoundArray.SetValue(1, 0);
You can use Array.CreateInstance.
See Array Types in .NET
Not simply. But you can certainly write your own class. It would have an array as a private variable, and the user would think his array starts at 1, but really it starts at zero and you're subtracting 1 from all of his array accesses.
You can write your own array class
I don't think if it's possible to modify the starting index of arrays.
I would create my own array using generics and handle it inside.
Just keep of const int named 'offset' with a value of one, and always add that to your subscripts in your code.
I don't think you can create non-zero based arrays in C#, but you could easily write a wrapper class of your own around the built in data structures.This wrapper class would hold a private instance of the array type you required; overloading the [] indexing operator is not allowed, but you can add an indexer to a class to make it behave like an indexable array, see here. The index function you write could then add (or subtract) 1, to all index's passed in.
You could then use your object as follows, and it would behave correctly:
myArrayObject[1]; //would return the zeroth element.
In VB6 you could change the array to start with 0 or 1, so I think VBScript can do the same. For C#, it's not possible but you can simply add NULL value in the first [0] and start real value at [1]. Of course, this is a little dangerous...
C# handles arrays much differently than C or C++ does. It treats them as an object for one thing, although they do have a fixed size. So I have some questions about arrays in C#:
If I create an array new int[10] will the Length property be guaranteed to be 10 or does C# try and resize the array if I get close to filling it up?
If I need to resize the array, do I have to create a new one with a larger size and then copy over each element in the array, or can I simply add more space without copying the elements over.
EDIT: it looks like you can use Array.Copy to copy the array over.
The List collection in C# seems like a dynamically sized array (maybe a mix between arrays and linked lists). If I use a List instead of an array, can I control its size? (i.e. force it to be length 10, then set its size to 20 if I need more space)
If I create an array new int[10] will the Length property be guaranteed to be 10 or does C# try and resize the array if I get close to filling it up?
It'll be 10. Always 10.
If I need to resize the array, do I have to create a new one with a larger size and then copy over each element in the array, or can I simply add more space without copying the elements over.
You need to resize it and copy. There are some helper methods that make this easier, like Array.Resize - but make no mistake that it is creating a new array and using Array.Copy to put everything there. If you need a resizable collection, use List<T>.
The List collection in C# seems like a dynamically sized array (maybe a mix between arrays and linked lists). If I use a List instead of an array, can I control its size? (i.e. force it to be length 10, then set its size to 20 if I need more space).
The size is controlled automatically. It will grow when needed. There is a constructor overload to accept the initial size. Internally, it also uses an array that is being resized when needed. When it's filled; it grows by double of its current capacity, and copies everything in the new underlying array in the list. But all that magic happens behind the scenes. If you want to manually resize the internal array of the List<T>, set the Capacity property to the number of items.
1) Yes, the Length will be 10.
2) Yes you have to create another one and copy the members. The Array class provides a method for that but you can't avoid the copying.
3) A list is indeed more convenient. You control its length (Count) by adding or removing members.
As a consequence, arrays are used less frequently in C#. We prefer List<T> classes (which could be using arrays under the covers). But they do incur some overhead.
Use arrays for low-level or fixed-size problems. Also there are no good (fast) multi-dim List classes.
Yes, arrays defined like that have a fixed size.
Yes, if you wish to extend you'll have to create a new Array
Yes, you can specify an initial capacity, with all values initializes to the default of the type stored. Extending happens automatically.
No
If you don't know the size of the array, and if the collection has to grow, use a List<T> instead. A List uses an array internally, but the List takes care of resizing the array if necessary.
The List will grow automatically as needed. You can set it's initiali Capacity though.
Arrays are of a fixed size. If you want to change the size of an array, allocate a new one, and copy the items into it using Array.Copy (or Array.Resize).
It is recommended to use List<T> instead, if you are regularly doing this. That handles all the resizing for you. You can specify an initial capacity when you create the list, but if you add more than the capacity the backing array is automatically resized to fit the extra items.
quick n dirty ;)
If I create an array new int[10] will the Length property be guaranteed to be 10 or does C# try and resize the array if I get close to filling it up?
NO
If I need to resize the array, do I have to create a new one with a larger size and then copy over each element in the array, or can I simply add more space without copying the elements over.
YES
The List collection in C# seems like a dynamically sized array (maybe a mix between arrays and linked lists). If I use a List instead of an array, can I control its size? (i.e. force it to be length 10, then set its size to 20 if I need more space)
If you construct your list without a capacity it will grow. You can set the maximum size using the constructor like...
List<string> list = new List<string>(10);
C# creates array of length 10 and don't resize it.
You can use list, you can't resize arrays.
Yes you can set list Capacity.
Capacity is the number of elements that the List(Of T) can store
before resizing is required, while Count is the number of elements
that are actually in the List(Of T).
I have an array of items that are time sensitive. After an amount of time, the last item needs to fall off and a new item is put at the beginning.
What is the best way to do this?
I would suggest using a queue, just a special instance of an array or list. When your timed event occurs, pop the last item from the queue, and then push your new item on.
Probably the easiest way to do this with an array is to use a circular index. Rather than always looking at array[n], you would reference array[cIndex] (where cIndex referrs to the item in the array being indexed (cIndex is incremented based on the arraySize (cIndex % arraySize)).
When you choose to drop the oldest item in the array, you would simply reference the element located at ((cIndex + (arraySize - 1)) % arraySize).
Alternatively, you could use a linkedList approach.
Use a Queue instead.
By using a Queue, preferably one implemented using a linked-list.
Have a look at using a Queue rather than a simple array.
A queue would work if there a fixed number of items.
Given that the 'amount of time' is known, how about a SortedDictionary with a DateTime key and override the Add method to remove all items with keys that are too old.
LinkedList<T> has AddFirst and RemoveLast members that should work perfectly.
EDIT: Looking at the Queue docs, it seems they use an internal array. As long as the implementation uses a circular-array type algorithm performance should be fine.
In csharp 3 you can do:
original = new[] { newItem }.Concat(
original.Take(original.Count() - 1)).ToArray()
But you are probably better off using a specialised datastructure
Queue is great for FIFO arrays. For generic array handling, use List(T)'s
Insert(0, x) and RemoveAt(0) methods to put or remove items in front of the list, for example.
Technically you need a deque. A queue has items pushed and popped off one end only. A deque is open at both ends.
Most languages will allow array manipulation, just remove the first element and put another one on the end.
Alternatively you can shift every element, by looping. Just replace each element (starting from the oldest) with its neighbour. Then place the new item in the last element.
If you know that your deque won't go above a certain size, then you can make it circular. You'll need two pointers to tell you where the two ends are though. Adding and removing items, will increase/decrease your pointers accordingly. You'll have to detect a buffer overflow condition (i.e. your pointers 'cross'). And you'll have to use modular arithmetic so your pointers go in a circle around the array.
Or you could time stamp each element in the array and remove them when they become too 'old'. You can either do this by keeping a separate array indexed in the same way, or by having an array of two element arrays, with the time stamp stored in one of the sub-elements.
If you're looking for the fastest way of doing this, it's going to be a circular array: you keep track of your current position in the array (ndx), and the end of the array (end), so when you insert an item, you implicitly eliminate the oldest item.
A circular array is the fastest implementation of a fixed-size queue that I know of.
For example, in C/C++ it would look like this for ints (quitting when you get a 0):
int queue[SIZE];
int ndx=0; // start at the beginning of the array
int end=SIZE-1;
int newitem;
while(1){
cin >> newitem;
if(!newitem) // quit if it's a 0
break;
if(ndx>end) // need to loop around the end of the array
ndx=0;
queue[ndx] = newitem;
ndx++
}
Lots of optimization could be done, but if you want to built it yourself, this is the fastest route.
If you don't care about performance, use a shipped Queue object because it should be generalized.
It may or may not be optimized, and it may not support a fixed size list, so be sure to check the documentation on it before using.
Is it possible in c# to initialize an array in, for example, subindex 1?
I'm working with Office interop, and every property is an object array that starts in 1 (I assume it was originally programed in VB.NET), and you cannot modify it, you have to set the entire array for it to accept the changes.
As a workaround I am cloning the original array, modifying that one, and setting it as a whole when I'm done.
But, I was wondering if it was possible to create a new non-zero based array
It is possible to do as you request see the code below.
// Construct an array containing ints that has a length of 10 and a lower bound of 1
Array lowerBoundArray = Array.CreateInstance(typeof(int), new int[1] { 10 }, new int[1] { 1 });
// insert 1 into position 1
lowerBoundArray.SetValue(1, 1);
//insert 2 into position 2
lowerBoundArray.SetValue(2, 2);
// IndexOutOfRangeException the lower bound of the array
// is 1 and we are attempting to write into 0
lowerBoundArray.SetValue(1, 0);
You can use Array.CreateInstance.
See Array Types in .NET
Not simply. But you can certainly write your own class. It would have an array as a private variable, and the user would think his array starts at 1, but really it starts at zero and you're subtracting 1 from all of his array accesses.
You can write your own array class
I don't think if it's possible to modify the starting index of arrays.
I would create my own array using generics and handle it inside.
Just keep of const int named 'offset' with a value of one, and always add that to your subscripts in your code.
I don't think you can create non-zero based arrays in C#, but you could easily write a wrapper class of your own around the built in data structures.This wrapper class would hold a private instance of the array type you required; overloading the [] indexing operator is not allowed, but you can add an indexer to a class to make it behave like an indexable array, see here. The index function you write could then add (or subtract) 1, to all index's passed in.
You could then use your object as follows, and it would behave correctly:
myArrayObject[1]; //would return the zeroth element.
In VB6 you could change the array to start with 0 or 1, so I think VBScript can do the same. For C#, it's not possible but you can simply add NULL value in the first [0] and start real value at [1]. Of course, this is a little dangerous...