Is there a function to remove the last cell from array?
it's a string array like: {"a","b","c",""}.
The length of an array is immutable, but you can create a new array without the empty "" strings:
string[] newArray = myArray.Where(str => str != "").ToArray();
Erm... just resize it
Array.Resize(ref theArray, theArray.Length -1);
From the docs
public static void Resize(ref T[] array, int newSize)
If it's an array of strings, you can do something like:
string[] results = theArray.Where(s => !string.IsNullOrWhitespace(s)).ToArray();
If you are just going to iterate the results, there's no need to convert back into an array, and you can leave off the .ToArray() at the end.
Edit:
If you just want to remove the last cell, and not empty entries (as suggested by your edited version), you can do this using Array.Copy more efficiently than using the LINQ statement above:
string[] results = new string[theArray.Length - 1];
Array.Copy( theArray, results, results.Length );
An array is a fixed-size collection object. That makes it woefully inadequate for what you want to do. The best you could do is create another one with one less element. That's expensive.
Fix the real problem, this should be a List<string>, now it's simple.
var newArraySize = oldArray.Length - 1;
var newArray = new string[newArraySize];
Array.Copy(oldArray, newArray, newArraySize);
Create new array equal to existing array size -1
aNewArray = aOldArray
Ofcourse you could just null the last element in your array, but that would result in problems later. Otherwise, use a nice flexible list.
If you always want to get rid of the last element,
int[] a = new[] {1, 2, 3, 4, 5};
int[] b = new int[a.Length - 1];
Array.Copy(a, b, a.Length - 1);
Related
I have a block of several lines of text. I've split this like so:
var lines = mytext.Split(new string[] {Environment.NewLine},
StringSplitOptions.None);
Now, I need to get a subset of the lines - namely a remainder. In Python I would do something like this:
>>> lines = ['zero', 'one', 'two', 'three', 'four']
>>> lines[3:]
['three', 'four']
But this is obviously not legal syntax in .NET.
So I found the Array.Copy method, and figured, a hah! I'll just do this:
var newlines = new string[lines.Length-someAmount]{};
to get me a list I can copy into.
but then I got an error saying that I can't make an array like that - the number has to be known at compile time! Okay, well, I'll try something else - silly, but it should work, right?
var newlinesList = new List<string>(lines.Length-someAmount);
var newlines = newlinesList.ToArray();
Then I can use:
Array.Copy(lines, startIndex, bodylines, 0, lines.Length-startIndex);
Except for one problem - apparently ToArray() filters out the empty/null values, so I can't actually copy it.
So how do I create an array with the size unknown until runtime, or even better, how can I simply slice an array?
There are several ways. Perhaps the easiest is with LINQ:
var newArray = lines.Skip(3).ToArray();
And if you wanted to take just two items (assuming the lines array had more than 5), you'd write:
var newArray = lines.Skip(3).Take(2).ToArray();
Or, if you only wanted the first three:
var newArray = lines.Take(3).ToArray();
Which, I think, pretty much covers array slicing.
You absolutely can do that – just don't pass a list of elements:
var newlines = new string[lines.Length-someAmount];
int cursor = 3; //Number of element to start copying from
string[] newlines = new string[lines.Length - cursor];
Array.Copy(lines, cursor, newlines, 0, lines.Length - cursor);
I am looking for fastest way to extend an array.
No matter if only for length + 1 or length + x it has to be the most fastest way.
Here is an example:
var arr = new int [200];
for(int = 0; i < 200; i++)
arr[i] = i;
And now I want to extend arr for 5 items beginning at index position 20.
var arr2 = new int [] { 999, 999, 999, 999, 999 }
How do I place arr2 inside arr by using most fast way in terms of performance?
The result shall look like this
0,1,2,3,4....20, 999, 999, 999, 999, 999, 21, 22, 23, 24....199
Create a new array which is the size you want, then use the static Array.Copy method to copy the original arrays into the new one.
You can't "extend" an array, you can only create a bigger one and copy the original into it.
Also, consider using List<int> or LinkedList<> instead of an array, unless you require extremely fine-grained control over what is in memory.
It is far easier to use List. But if you have to use arrays, you have to create new array of size 205 and copy values from both source arrays, since array size is constant.
Your best bet is to use something like List<int> rather than an array. But if you must use an array:
int[] arr1 = new int[200];
// initialize array
int[] arr2 = new int[]{999, 999, 999, 999, 999};
int targetPos = 20;
// resizes the array, copying the items
Array.Resize(ref arr1, arr1.Length + arr2.Length);
// move the tail of the array down
Buffer.BlockCopy(arr1, 4*targetPos, arr1, 4*(targetPos+arr2.Length), 4*(arr1.Length - targetPos));
// copy arr2 to the proper position
Buffer.BlockCopy(arr2, 0, 4*arr1.targetPos, 4*arr2.Length);
It might be faster to create a new array and copy the items, like this.
int[] newArray = new int[arr1.Length + arr2.Length];
// copy first part of original array
Buffer.BlockCopy(arr1, 0, newArray, 0, 4*targetPos);
// copy second array
Buffer.BlockCopy(arr2, 0, newArray, 4*targetPos, 4*arr2.Length);
// copy remainder of original array
Buffer.blockCopy(arr1, 4*targetPos, newArray, 4*(targetPos + arr2.Length), 4*(arr1.Length - targetPos));
// and replace the original array
arr1 = newArray;
Which version is faster will depend on where targetPos is. The second version will be faster when targetPos is small. When targetPos is small, the first version has to copy a lot of data twice. The second version never copies more than it has to.
BlockCopy is kind of a pain to work with because it requires byte offsets, which is the reason for all the multiplications by four in the code. You might be better off using Array.Copy in the second version above. That will prevent you having to multiply everything by 4 (and forgetting sometimes).
If you know how long the array will be dimension it to that length,
var ints = new int[someFixedLength];
If you have a vauge idea of the length, use a generic list.
var ints = new List<int>(someVagueLength);
both types implement IList but, the List type handles the redimensioning of the internal array is generically the "most fast" way.
Note: the initial .Count of the List will be 0 but, the internal array will be dimensioned to size you pass to to the constructor.
If you need to copy data between arrays, the quickest way is Buffer.BlockCopy, so from your example
Buffer.BlockCopy(arr2, 0, arr, sizeof(int) * 20, sizeof(int) * 5);
copies all 5 ints from arr2 into indecies 20, 21 ... 24 of arr.
there is no faster way to do this with c# (currently).
An answer showing timing benchmarks is given here: Best way to combine two or more byte arrays in C# . If you consider the "array you insert into " as arrays 1 and 3, and the "array to be inserted" as array 2, then the "concatenate three arrays" example applies directly.
Note the point at the end of the accepted answer: the method that is faster at creating yields an array that is slower to access (which is why I asked if you cared about speed to create, or access speed).
using System.Linq you can do the following to extend an array by adding one new object to it...
int[] intA = new int[] { 1, 2, 3 };
int intB = 4;
intA = intA.Union(new int[] { intB }).ToArray();
...or you can extend an array by adding another array of items to it...
int[] intA = new int[] { 1, 2, 3 };
int[] intB = new int[] { 4, 5, 6 };
intA = intA.Union(intB).ToArray();
...or if you don't care about duplicates...
int[] intA = new int[] { 1, 2, 3 };
int[] intB = new int[] { 4, 5, 6 };
intA = intA.Concat(intB).ToArray();
Is it possible, in C#, to convert a multi-dimensional array into a 1D array without having to copy all the elements from one to the other, something like:
int[,] x = new int[3,4];
int[] y = (int[])x;
This would allow the use of x as if it were a 12-element 1D array (and to return it from a function as such), but the compiler does not allow this conversion.
As far as I'm aware, a 2D array (or higher number of dimensions) is laid out in contiguous memory, so it doesn't seem impossible that it could work somehow. Using unsafe and fixed can allow access through a pointer, but this doesn't help with returning the array as 1D.
While I believe I can just use a 1D array throughout in the case I'm working on at present, it would be useful if this function was part of an adapter between something which returns a multidimensional array and something else which requires a 1D one.
You can't, it's not possible in C# to convert array's this way. You maybe could do it by using a external dll ( C/C++ ), but then you need to keep your array at a fixed location.
Speed
Generally i would advice to avoid using a 2D array because theese are slow in C#, better use jagged-array or even better single dimensionals with a little bit of math.
Int32[] myArray = new Int32[xSize * ySize];
// Access
myArray[x + (y * xSize)] = 5;
In C#, arrays cannot be resized dynamically. One approach is to use System.Collections.ArrayList instead of a native array. Another (faster) solution is to re-allocate the array with a different size and to copy the contents of the old array to the new array. The generic function resizeArray (below) can be used to do that.
One example here :
// 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; }
You can already iterate over a multidim as if it were a 1 dimensional array:
int[,] data = { { 1, 2, 3 }, { 3, 4, 5 } };
foreach (int i in data)
... // i := 1 .. 5
And you could wrap a 1-dim array in a class and provide an indexer property this[int x1, int x2].
But everything else will require unsafe code or copying. Both will be inefficient.
Riding on the back of Felix K.'s answer and quoting a fellow developer:
You can't convert a square to a line without losing information
try
int[,] x = {{1, 2}, {2, 2}};
int[] y = new int[4];
System.Buffer.BlockCopy(x, 0, y, 0, 4);
You cannot cast, you'll have to copy the elements:
int[] y = (from int i in y select i).ToArray();
I know this is kind of a dumb question, but does anyone have an elegant (or non-elegant) LINQ approach to transform a 2D array (object[,]) into a 1D array (object[]) comprised of the first dimension of the 2D array?
Example:
// I'd like to have the following array
object[,] dim2 = {{1,1},{2,2},{3,3}};
// converted into this kind of an array... :)
object[] dim1 = { 1, 2, 3 };
You claim that you want a 1D array (object[]) comprised of the first dimension of the 2D array, so I assume you are trying to select a subset of the original 2D array.
int[,] foo = new int[2, 3]
{
{1,2,3},
{4,5,6}
};
int[] first = Enumerable.Range(0, foo.GetLength(0))
.Select(i => foo[i, 0])
.ToArray();
// first == {1, 4}
#Elisha had posted an answer (didn't compile initially) also, which I was investigating this afternoon. I don't know why he deleted his answer, but I carried on with his code example until everything got worked out, and it also gives me what I need:
object[,] dim2 =
{{"ADP", "Australia"}, {"CDN", "Canada"}, {"USD", "United States"}};
object[] dim1 = dim2.Cast<object>().ToArray();
// dim1 = {"ADP", "CDN", "USD"}
This code compiles and returns the expected results. I glad about the .Cast(), and that I only needed the first dimension, not the second.
In general, for a collection of collections (instead of an array of arrays), you can do:
mainCollection.Select(subCollection => subCollection.First());
I need to get an array containing reversed alternate elements of the original array.
For example: an array containing elements {12,56,67}.
I need to get an array containing {67,12}
(reversing array to get {67,56,12} then take alternate elements means {67,12})
I need to do this in c#
This won't be the shortest answer you'll get, but it seems fairly optimised to me.
int[] rgIn = new int[]{0,1,2,3,4,5};
int[] rgOut = new int[rgIn.Length / 2];
int ixOut = 0;
for (int ixIn = rgIn.Length - 2; ixIn >= 0; ixIn -= 2)
{
rgOut[ixOut++] = rgIn[ixIn];
}
If you're using C# 3, try this:
int[] array = {1,2,3,4,5,6};
var x = array.Reverse().Where( (n,i) => i % 2 !=0);
Where is an extension method (new in C# 3.0) which forms part of a language feature called LINQ. It filters a sequence based on a predicate. In the sample above, n is the element of the sequence and i is the zero based index of the element in the sequence. Both are strongly typed. The predicate i%2!=0 is saying that the index of the element is not directly divisible by 2, so what we are saying is reverse the list and select the odd elements from it.
Not the most efficient solution, but short and concise.