What is the slickest way to initialize an array of dynamic size in C# that you know of?
This is the best I could come up with
private bool[] GetPageNumbersToLink(IPagedResult result)
{
if (result.TotalPages <= 9)
return new bool[result.TotalPages + 1].Select(b => true).ToArray();
...
If by 'slickest' you mean fastest, I'm afraid that Enumerable.Repeat may be 20x slower than a for loop.
See http://dotnetperls.com/initialize-array:
Initialize with for loop: 85 ms [much faster]
Initialize with Enumerable.Repeat: 1645 ms
So use Dotnetguy's SetAllValues() method.
use Enumerable.Repeat
Enumerable.Repeat(true, result.TotalPages + 1).ToArray()
EDIT: as a commenter pointed out, my original implementation didn't work. This version works but is rather un-slick being based around a for loop.
If you're willing to create an extension method, you could try this
public static T[] SetAllValues<T>(this T[] array, T value) where T : struct
{
for (int i = 0; i < array.Length; i++)
array[i] = value;
return array;
}
and then invoke it like this
bool[] tenTrueBoolsInAnArray = new bool[10].SetAllValues(true);
As an alternative, if you're happy with having a class hanging around, you could try something like this
public static class ArrayOf<T>
{
public static T[] Create(int size, T initialValue)
{
T[] array = (T[])Array.CreateInstance(typeof(T), size);
for (int i = 0; i < array.Length; i++)
array[i] = initialValue;
return array;
}
}
which you can invoke like
bool[] tenTrueBoolsInAnArray = ArrayOf<bool>.Create(10, true);
Not sure which I prefer, although I do lurv extension methods lots and lots in general.
I would actually suggest this:
return Enumerable.Range(0, count).Select(x => true).ToArray();
This way you only allocate one array. This is essentially a more concise way to express:
var array = new bool[count];
for(var i = 0; i < count; i++) {
array[i] = true;
}
return array;
Many times you'd want to initialize different cells with different values:
public static void Init<T>(this T[] arr, Func<int, T> factory)
{
for (int i = 0; i < arr.Length; i++)
{
arr[i] = factory(i);
}
}
Or in the factory flavor:
public static T[] GenerateInitializedArray<T>(int size, Func<int, T> factory)
{
var arr = new T[size];
for (int i = 0; i < arr.Length; i++)
{
arr[i] = factory(i);
}
return arr;
}
Untested, but could you just do this?
return result.Select(p => true).ToArray();
Skipping the "new bool[]" part?
Related
I would like to create an array with of length X, and i would like the following 'inteligence'
if , for exemple, X = 6,
myArray[x] = [0,1,2,3,4,5]
For the moment, i do
int[] availableIndex = new int[DestructiblesCubes.Count];
for (var i = 0; i < availableIndex.Length; i++)
{
availableIndex[i] = i;
}
But, i'm curious, is there a better (the faster way to execute it) and/or the faster(the shortest char length) way?
Thanks :)
This is short way to implement this. Not the performance best solution.
Enumerable.Range(0, 10).ToArray()
MSDN description for Enumerable.Range
I think the fastest method uses the unsafe context together with a proper fixed pointer to the array, as demonstrated below:
/*const*/ int availableIndex_Length = 6;
int[] availableIndex = new int[availableIndex_Length];
unsafe {
fixed(int* p = &availableIndex[0]) {
for(int i = 0; i < availableIndex_Length; ++i) {
*(p+i) = i;
}
}
}
This can be refactored to a method, optionally inlined:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static unsafe void FillRange(ref int[] array) {
int length = array.Length;
fixed(int* p = &array[0]) {
for(int i = 0; i < length; ++i) {
*(p + i) = i;
}
}
}
static void Main(string[] args) {
// Example usage:
int[] availableIndices = new int[6];
FillRange(ref availableIndices);
// Test if it worked:
foreach(var availableIndex in availableIndices) {
Console.WriteLine(availableIndex);
}
Console.ReadKey(true);
}
You could try this:
unsafe
{
int[] availableIndex = new int[DestructiblesCubes.Count];
int length = availableIndex.Length;
int n = 0;
fixed(int *p = availableIndex) {
while(n < length) *p++ = n++;
}
}
may be faster, depending on the optimization stage of your compiler.
The only optimisation I can see to apply to your code as it stands is to count down to zero, but any increase in performance will be tiny
int[] availableIndex = new int[DestructiblesCubes.Count];
for (var i = availableIndex.Length-1; i >= 0; i--)
{
availableIndex[i] = i;
}
Otherwise, especially if you're talking large arrays, one thing to try would be to create an array greater than your max envisioned value of DestructiblesCubes.Count and
Intialize that array as above, then use Array.Copy when you want the smaller array.
I would be confident that no code we hand roll will be faster than a single call to Array.Copy.
int[] availableIndex = new int[DestructiblesCubes.Count];
Array.Copy(LargeArray, availableIndex, availableIndex.Length);
Otherwise I can't think of anything that might be faster than the code you have.
I have list of structure. I want to modify a particular data from the structure.
And the structure is at the particular index location of the List.
I want to do something like this:
struct sample
{
int a;
string name;
}
List<sample> list = new List<sample>();
for(int i=0; i < list.Count; i++)
{
list[i].a = someotherlist[i].data;
}
The problem is that the list indexer creates a copy of the struct, i.e. it is really:
for(int i=0; i < list.Count; i++)
{
var completelyIsolatedClone = list[i];
completelyIsolatedClone.a = someotherlist[i].data;
}
The compiler is preventing you making an obvious mistake. The code you have uses the get, mutates a separate copy of the data, but never puts it back - so your change doesn't do anything useful. Note that the Mono folks think it would be nice if it worked your way, though: http://tirania.org/blog/archive/2012/Apr-11.html
Note that an array works differently; with an array you are touching the struct in place, so the following would work fine:
for(int i=0; i < list.Count; i++)
{
someArray[i].a = someotherlist[i].data;
}
Another approach is to copy the data out (the get accessor), mutate it, and put it back:
for(int i=0; i < list.Count; i++)
{
var completelyIsolatedClone = list[i];
completelyIsolatedClone.a = someotherlist[i].data;
list[i] = completelyIsolatedClone;
}
or better, acoid mutable structs completely, perhaps with a method that applies the change to a new copy:
for(int i=0; i < list.Count; i++)
{
list[i] = list[i].SetA(someotherlist[i].data);
}
where SetA creates a new struct, like DateTime.AddDays etc, i.e.
public SomeType SetA(int a) {
return new SomeType(this.X, this.Y, a, this.Z);
}
The reason you can't do it is because Sample is a struct, if you change it to a class then you can modify it. Structures are passed by value, that is, when a structure is returned by a method, a copy of the structure is returned, not the orginal structure. So when list[i].a = someotherlist[i].data; is run, you are actually modifying the copy and the orginal structure is not being changed. The compilers prevents you from doing this as it is probably not what you had intended.
You may look at this thread Why couldnot I modify the value of item from Generic Collections) ?
I just modified my code as bellow and it works fine for me
public struct test
{
public int data;
public string name;
public int port_index;
}
static void Main(string[] args)
{
List<test> look_up = new List<test>();
test obj;
obj.data = 1;
obj.port_index = 0;
obj.name = "aaaa";
look_up.Add(obj);
test obj1;
obj1.data=3;
obj1.port_index=1;
obj1.name="sssss";
look_up.Add(obj1);
for(int i=0;i<look_up.Count;i++)
{
if (i == 1)
{
test temp = look_up[i];
temp.data = 5;
look_up[i] = temp;
}
}
}
I'm trying something like that:
class point
{
public int x;
public int y;
}
point[] array = new point[100];
array[0].x = 5;
and here's the error:
Object reference not set to an instance of an object. (# the last line)
whats wrong? :P
It only creates the array, but all elements are initialized with null.
You need a loop or something similar to create instances of your class.
(foreach loops dont work in this case)
Example:
point[] array = new point[100];
for(int i = 0; i < 100; ++i)
{
array[i] = new point();
}
array[0].x = 5;
When you do
point[] array = new point[100];
you create an array, not 100 objects. Elements of the array are null. At that point you have to create each element:
array[0] = new point();
array[0].x = 5;
You can change class point to struct point in that case new point[500] will create an array of points initialized to 0,0 (rather than array of null's).
As the other answers explain, you need to initialize the objects at each array location. You can use a method such as the following to create pre-initialized arrays
T[] CreateInitializedArray<T>(int size) where T : new()
{
var arr = new T[size];
for (int i = 0; i < size; i++)
arr[i] = new T();
return arr;
}
If your class doesn't have a parameterless constructor you could use something like:
T[] CreateInitializedArray<T>(int size, Func<T> factory)
{
var arr = new T[size];
for (int i = 0; i < size; i++)
arr[i] = factory();
return arr;
}
LINQ versions for both methods are trivial, but slightly less efficient I believe
int[] asd = new int[99];
for (int i = 0; i < 100; i++)
asd[i] = i;
Something like that?
Sometimes LINQ comes in handy. It may provide some extra readability and reduce boilerplate and repetition. The downside is that extra allocations are required: enumerators are created and ToArray does not know the array size beforehand, so it might need to reallocate the internal buffer several times. Use only in code whose maintainability is much more critical than its performance.
using System.Linq;
const int pointsCount = 100;
point[] array = Enumerable.Range(0, pointsCount)
.Select(_ => new point())
.ToArray()
I have many Action objects with a property long Timestamp. I want to do something like this:
Assert.IsTrue(a1.Timestamp < a2.Timestamp < a3.Timestamp < ... < an.Timestamp);
Unfortunately, this syntax is illegal. Is there a built-in way or a extension\LINQ\whatever way to perform this?
Note that it's target for a unit test class, so get crazy. I don't care about performance, readability and etc.
private static bool isValid(params Action[] actions)
{
for (int i = 1; i < actions.Length; i++)
if (actions[i-1].TimeStamp >= actions[i].TimeStamp)
return false;
return true;
}
Assert.IsTrue(isValid(a1,a2,...,an));
How about:
Action[] actions = { a1, a2, a3, ... an };
Assert.IsTrue
(actions.Skip(1)
.Zip(action, (next, prev) => prev.Timestamp < next.Timestamp)
.All(b => b));
public bool InOrder(params long[] data)
{
bool output = true;
for (int i = 0; i <= data.Count-1;i++)
{
output &= data[i] < data[i + 1];
}
return output;
}
I used a for loop as this guarantees the order of the iteration, what a foreach loop wouldn't do.
by assuming actions is a List or array:
actions.Skip(1).Where((x,index)=>x.Timespan > actions[i].Timespan).All(x=>x)
I was shocked to find out today that C# does not support dynamic sized arrays. How then does a VB.NET developer used to using ReDim Preserve deal with this in C#?
At the beginning of the function I am not sure of the upper bound of the array. This depends on the rows returned from the database.
VB.NET doesn't have the idea of dynamically sized arrays, either - the CLR doesn't support it.
The equivalent of "Redim Preserve" is Array.Resize<T> - but you must be aware that if there are other references to the original array, they won't be changed at all. For example:
using System;
class Foo
{
static void Main()
{
string[] x = new string[10];
string[] y = x;
Array.Resize(ref x, 20);
Console.WriteLine(x.Length); // Prints out 20
Console.WriteLine(y.Length); // Still prints out 10
}
}
Proof that this is the equivalent of Redim Preserve:
Imports System
Class Foo
Shared Sub Main()
Dim x(9) as String
Dim y as String() = x
Redim Preserve x(19)
Console.WriteLine(x.Length)
Console.WriteLine(y.Length)
End Sub
End Class
The two programs are equivalent.
If you truly want a dynamically sized collection, you should use List<T> (or something similar). There are various issues with using arrays directly - see Eric Lippert's blog post for details. That's not to say you should always avoid them, by any means - but you need to know what you're dealing with.
Use ArrayLists or Generics instead
Use a List<T>. It will dynamically size as needed.
You really shouldn't be using ReDim, it can be very expensive. I prefer List(Of T), but there are many options in this area.
That said, you had a question and here is your answer.
x = (int[]) Utils.CopyArray((Array) x, new int[10]);
I couldn't help but notice that none of the above answers approach the concept of multidimensional arrays. That being said, here's an example. The array in question is predefined as x.
int[,] temp = new int[newRows, newCols];
int minRows = Math.Min(newRows, x.GetUpperBound(0) + 1);
int minCols = Math.Min(newCols, x.GetUpperBound(1) + 1);
for (int i = 0; i < minRows ; ++i)
for (int j = 0; j < minCols; ++j)
temp[i, j] = x[i, j];
x = temp;
Just for fun, here's one way to use generics in order to redim/extend a unidimensional array (add one more "row") :
static T[] Redim<T>(T[] arr, bool preserved)
{
int arrLength = arr.Length;
T[] arrRedimed = new T[arrLength + 1];
if (preserved)
{
for (int i = 0; i < arrLength; i++)
{
arrRedimed[i] = arr[i];
}
}
return arrRedimed;
}
And one to add n rows (though this doesn't prevent user from undersizing the array, which will throw an error in the for loop) :
static T[] Redim<T>(T[] arr, bool preserved, int nbRows)
{
T[] arrRedimed = new T[nbRows];
if (preserved)
{
for (int i = 0; i < arr.Length; i++)
{
arrRedimed[i] = arr[i];
}
}
return arrRedimed;
}
I'm sure you get the idea.
For a multidimensional array (two dimensions), here's one possibility:
static T[,] Redim<T>(T[,] arr, bool preserved)
{
int Ubound0 = arr.GetUpperBound(0);
int Ubound1 = arr.GetUpperBound(1);
T[,] arrRedimed = new T[Ubound0 + 1, Ubound1];
if (preserved)
{
for (int j = 0; j < Ubound1; j++)
{
for (int i = 0; i < Ubound0; i++)
{
arrRedimed[i, j] = arr[i, j];
}
}
}
return arrRedimed;
}
In your program, use this with or even without the type specified, the compiler will recognize it :
int[] myArr = new int[10];
myArr = Redim<int>(myArr, true);
or
int[] myArr = new int[10];
myArr = Redim(myArr, true);
Not sure if all this is really relevant though. =D
Please feel free to correct me or improve my code. ;)
Even though it's a long time ago it might help someone looking for a simple solution - I found something great in another forum:
//from Applied Microsoft.NET framework Programming - Jeffrey Richter
public static Array RedimPreserve(Array origArray, Int32 desiredSize)
{
System.Type t = origArray.GetType().GetElementType();
Array newArray = Array.CreateInstance(t, desiredSize);
Array.Copy(origArray, 0, newArray, 0, Math.Min(origArray.Length, desiredSize));
return newArray;
}
Source: https://social.msdn.microsoft.com/Forums/en-US/6759816b-d525-4752-a3c8-9eb5f4a5b194/redim-in-c?forum=csharplanguage