C# quickest way to shift array

前端 未结 20 1202
礼貌的吻别
礼貌的吻别 2020-12-01 01:35

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

相关标签:
20条回答
  • 2020-12-01 02:28

    Use the Array.Copy() method as in

    int?[] myArray = new int?[]{0,1,2,3,4};
    Array.Copy(myArray, 1, myArray, 0, myArray.Length - 1);
    myArray[myArray.Length - 1] = null
    

    The Array.Copy is probably the way, Microsoft wanted us to copy array elements...

    0 讨论(0)
  • 2020-12-01 02:29

    For any pour soul finding this thread and about to implement one of the highly rated answers. All of them are trash, I'm not sure why that is. Maybe Dested asked for a new array implementation at first or something that has now been removed from the question. Well if you simply want to shift the array and don't need a new one, see an answer like tdaines's answer. And read up on things like the Circular Buffer / Ring Buffer : http://en.wikipedia.org/wiki/Circular_buffer. No moving of the actual data is necessary. The performance of shifting an array should not be tied to the size of the array.

    0 讨论(0)
  • 2020-12-01 02:30

    You can use the same array as source and destination for fast in-place copy:

    static void Main(string[] args)
            {
                int[] array = {0, 1, 2, 3, 4, 5, 6, 7};
                Array.ConstrainedCopy(array, 1, array, 0, array.Length - 1);
                array[array.Length - 1] = 0;
            }
    
    0 讨论(0)
  • 2020-12-01 02:31
    using System;
    using System.Threading;
    
    namespace ShiftMatrix
    {
        class Program
        {
            static void Main(string[] args)
            {
    
                MatrixOperation objMatrixOperation = new MatrixOperation();
    
                //Create a matrix
                int[,] mat = new int[,]
            {
            {1, 2},
            {3,4 },
            {5, 6},
            {7,8},
            {8,9},
            };
    
                int type = 2;
                int counter = 0;
                if (type == 1)
                {
                    counter = mat.GetLength(0);
                }
                else
                {
                    counter = mat.GetLength(1);
                }
                while (true)
                {
                    for (int i = 0; i < counter; i++)
                    {
                        ShowMatrix(objMatrixOperation.ShiftMatrix(mat, i, type));
                        Thread.Sleep(TimeSpan.FromSeconds(2));
                    }
                }
            }
            public static void ShowMatrix(int[,] matrix)
            {
                int rows = matrix.GetLength(0);
                int columns = matrix.GetLength(1);
                for (int k = 0; k < rows; k++)
                {
                    for (int l = 0; l < columns; l++)
                    {
                        Console.Write(matrix[k, l] + " ");
                    }
                    Console.WriteLine();
                }
            }
        }
        class MatrixOperation
        {
            public int[,] ShiftMatrix(int[,] origanalMatrix, int shift, int type)
            {
                int rows = origanalMatrix.GetLength(0);
                int cols = origanalMatrix.GetLength(1);
    
                int[,] _tmpMatrix = new int[rows, cols];
                if (type == 2)
                {
                    for (int x1 = 0; x1 < rows; x1++)
                    {
                        int y2 = 0;
                        for (int y1 = shift; y2 < cols - shift; y1++, y2++)
                        {
                            _tmpMatrix[x1, y2] = origanalMatrix[x1, y1];
                        }
                        y2--;
                        for (int y1 = 0; y1 < shift; y1++, y2++)
                        {
                            _tmpMatrix[x1, y2] = origanalMatrix[x1, y1];
                        }
                    }
                }
                else
                {
                    int x2 = 0;
                    for (int x1 = shift; x2 < rows - shift; x1++, x2++)
                    {
                        for (int y1 = 0; y1 < cols; y1++)
                        {
                            _tmpMatrix[x2, y1] = origanalMatrix[x1, y1];
                        }
                    }
                    x2--;
                    for (int x1 = 0; x1 < shift; x1++, x2++)
                    {
                        for (int y1 = 0; y1 < cols; y1++)
                        {
                            _tmpMatrix[x2, y1] = origanalMatrix[x1, y1];
                        }
                    }
    
                }
                return _tmpMatrix;
            }
        }
    
    }
    
    0 讨论(0)
  • 2020-12-01 02:32

    If you own the memory you could consider using Unsafe Code and good old fashioned pointers.

    Make yourself a memory stream and lock it down or use Marshal.AllocHGlobal Construct all your arrays in it with a little bit of padding at the beginning and end. increment or decrement all of the array pointers at once. You'll still need to loop back and set your nulls.

    If you need to selectively increment or decrement the arrays you would have to add padding between them.

    Arrays are incredibly low level data structures, if you treat them in a low level way you can get huge performance out of them.

    A baytrail doing this could outperform Jason's with all its copying 8 Core Intel Xeon E5450 @ 3.00GHz

    0 讨论(0)
  • 2020-12-01 02:34

    Here is my solution, similar to Task's in that it is a simple Array wrapper and that it takes O(1) time to shift the array to the left.

    public class ShiftyArray<T>
    {
        private readonly T[] array;
        private int front;
    
        public ShiftyArray(T[] array)
        {
            this.array = array;
            front = 0;
        }
    
        public void ShiftLeft()
        {
            array[front++] = default(T);
            if(front > array.Length - 1)
            {
                front = 0;
            }
        }
    
        public void ShiftLeft(int count)
        {
            for(int i = 0; i < count; i++)
            {
                ShiftLeft();
            }
        }
    
        public T this[int index]
        {
            get
            {
                if(index > array.Length - 1)
                {
                    throw new IndexOutOfRangeException();
                }
    
                return array[(front + index) % array.Length];
            }
        }
    
        public int Length { get { return array.Length; } }
    }
    

    Running it through Jason Punyon's test code...

    int?[] intData = Enumerable.Range(1, 100).Cast<int?>().ToArray();
    ShiftyArray<int?> array = new ShiftyArray<int?>(intData);
    
    Stopwatch watch = new Stopwatch();
    watch.Start();
    
    for(int i = 0; i < 1000000; i++)
    {
        array.ShiftLeft();
    }
    
    watch.Stop();
    
    Console.WriteLine(watch.ElapsedMilliseconds);
    

    Takes ~29ms, regardless of the array size.

    0 讨论(0)
提交回复
热议问题