How can I quickly shift all the items in an array one to the left, padding the end with null?
For example, [0,1,2,3,4,5,6] would become [1,2,3,4,5,6,null]
Ed
You might do it like this:
var items = new int?[] { 0, 1, 2, 3, 4, 5, 6 }; // Your array
var itemList = new List<int?>(items); // Put the items in a List<>
itemList.RemoveAt(1); // Remove the item at index 1
itemList.Add(null); // Add a null to the end of the list
items = itemList.ToArray(); // Turn the list back into an array
Of course, it would be more efficient to get rid of the array entirely and just use a List<>. You could then forget the first line and last line and do it like this:
var itemList = new List<int?> { 0, 1, 2, 3, 4, 5, 6 };
itemList.RemoveAt(1); // Remove the item at index 1
itemList.Add(null); // Add a null to the end of the list
Array copying is an O(n) operation and creates a new array. While array copying can certainly be done quickly and efficiently, the problem you've stated can actually be solved in an entirely different way without (as you've requested) creating a new array/data structure and only creating one small wrapping object instance per array:
using System;
using System.Text;
public class ArrayReindexer
{
private Array reindexed;
private int location, offset;
public ArrayReindexer( Array source )
{
reindexed = source;
}
public object this[int index]
{
get
{
if (offset > 0 && index >= location)
{
int adjustedIndex = index + offset;
return adjustedIndex >= reindexed.Length ? "null" : reindexed.GetValue( adjustedIndex );
}
return reindexed.GetValue( index );
}
}
public void Reindex( int position, int shiftAmount )
{
location = position;
offset = shiftAmount;
}
public override string ToString()
{
StringBuilder output = new StringBuilder( "[ " );
for (int i = 0; i < reindexed.Length; ++i)
{
output.Append( this[i] );
if (i == reindexed.Length - 1)
{
output.Append( " ]" );
}
else
{
output.Append( ", " );
}
}
return output.ToString();
}
}
By wrapping and controlling access to the array in this manner, we can now demonstrate how the problem was solved with an O(1) method call...
ArrayReindexer original = new ArrayReindexer( SourceArray );
Console.WriteLine( " Base array: {0}", original.ToString() );
ArrayReindexer reindexed = new ArrayReindexer( SourceArray );
reindexed.Reindex( 1, 1 );
Console.WriteLine( "Shifted array: {0}", reindexed.ToString() );
Will produce the output:
Base array: [ 0, 1, 2, 3, 4, 5, 6 ]
Shifted array: [ 0, 2, 3, 4, 5, 6, null ]
I'm willing to bet that there will be a reason that such a solution won't work for you, but I believe this does match your initial stated requirements. 8 )
It's often helpful to think about all the different kinds of solutions to a problem before implementing a specific one, and perhaps that might be the most important thing that this example can demonstrate.
Hope this helps!