una suma puede parte matriz matriciales matrices inversa grabar fórmula funciones ejemplos crear con como cambiar c# arrays performance

suma - C#forma más rápida de cambiar matriz



no se puede cambiar parte de una matriz excel (19)

¿Cómo puedo cambiar rápidamente todos los elementos en una matriz uno a la izquierda, rellenando el final con nulo?

Por ejemplo, [0,1,2,3,4,5,6] se convertiría en [1,2,3,4,5,6, nulo]

Edición: dije rápidamente, pero creo que quise decir de manera eficiente. Necesito hacer esto sin crear una lista o alguna otra estructura de datos. Esto es algo que debo hacer cientos de miles de veces en el menor tiempo posible.


¿No podría usar un System.Collections.Generic.Queue en lugar de una matriz?

Siento que necesita realizar acciones sobre su valor para descartarlo, por lo tanto, usar una cola parece ser más apropiado:

// dummy initialization System.Collections.Generic.Queue<int> queue = new Queue<int>(); for (int i = 0; i < 7; ++i ) { queue.Enqueue(i); }// add each element at the end of the container // working thread if (queue.Count > 0) doSomething(queue.Dequeue());// removes the last element of the container and calls doSomething on it


Aquí está mi arnés de prueba ...

var source = Enumerable.Range(1, 100).Cast<int?>().ToArray(); var destination = new int?[source.Length]; var s = new Stopwatch(); s.Start(); for (int i = 0; i < 1000000;i++) { Array.Copy(source, 1, destination, 0, source.Length - 1); } s.Stop(); Console.WriteLine(s.Elapsed);

Estos son los resultados de rendimiento de 1 millón de iteraciones de cada solución (8 Core Intel Xeon E5450 @ 3.00GHz)

100 elements 10000 elements For Loop 0.390s 31.839s Array.Copy() 0.177s 12.496s Aaron 1 3.789s 84.082s Array.ConstrainedCopy() 0.197s 17.658s

Haz la elección por ti mismo :)


Esta es mi solución, similar a la de Tareas en cuanto a que es un envoltorio simple de Array y que toma O (1) tiempo para desplazar el arreglo hacia la izquierda.

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; } } }

Ejecutarlo a través del código de prueba de Jason Punyon ...

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);

Toma ~ 29ms, independientemente del tamaño de la matriz.


La copia de matriz es una operación O (n) y crea una nueva matriz. Si bien la copia de matriz puede realizarse de manera rápida y eficiente, el problema que ha planteado se puede resolver de una manera completamente diferente sin (como usted solicitó) crear una nueva matriz / estructura de datos y solo crear una pequeña instancia de objeto de envoltura por formación:

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(); } }

Al envolver y controlar el acceso a la matriz de esta manera, ahora podemos demostrar cómo se resolvió el problema con una llamada al método O (1) ...

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() );

Producirá la salida:

Matriz base: [0, 1, 2, 3, 4, 5, 6]
Matriz desplazada: [0, 2, 3, 4, 5, 6, nulo]

Estoy dispuesto a apostar que habrá una razón por la cual esa solución no funcionará para usted, pero creo que esto coincide con sus requisitos iniciales establecidos. 8)

A menudo es útil pensar en los diferentes tipos de soluciones a un problema antes de implementar uno específico, y tal vez eso sea lo más importante que este ejemplo pueda demostrar.

¡Espero que esto ayude!


La forma más rápida de hacerlo es usar Array.Copy , que en la implementación final utiliza una operación de transferencia de memoria masiva (similar a memcpy):

var oldArray = new int?[] { 1, 2, 3, 4, 5, 6 }; var newArray = new int?[oldArray.Length]; Array.Copy(oldArray, 1, newArray, 0, oldArray.Length - 1); // newArray is now { 2, 3, 4, 5, 6, null }

Editado: según la documentación:

Si sourceArray y destinationArray se superponen, este método se comporta como si los valores originales de sourceArray se conservaran en una ubicación temporal antes de que se sobrescriba destinationArray.

Entonces, si no desea asignar una nueva matriz, puede pasar la matriz original para el origen y el destino, aunque imagino que la compensación será un rendimiento algo más lento ya que los valores pasan por una posición de espera temporal.

Supongo que, como en cualquier investigación de este tipo, debería hacer una comparación rápida.


No puedes

  • asignar la matriz con un extra de 1000 elementos

  • tener una variable entera int base = 0

  • en lugar de acceder a[i] acceder a[base+i]

  • para hacer su turno, solo diga base++

Luego, después de haber hecho esto 1000 veces, cópielo y comience nuevamente.
De esta forma, solo haces la copia una vez cada 1000 turnos.

Viejo chiste
P: ¿Cuántas IBM 360s se necesitan para cambiar un registro por 1 bit?
A: 33. 32 para mantener los bits en su lugar, y 1 para mover el registro. (o algo así ...)


Puede usar la misma matriz como fuente y destino para una copia rápida en el lugar:

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; }


Puedes hacerlo así:

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

Por supuesto, sería más eficiente deshacerse de la matriz por completo y simplemente usar una lista <>. Entonces podrías olvidar la primera línea y la última línea y hacerlo así:

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


Respuesta incorrecta y ligeramente entretenida (¡gracias, estaré aquí toda la noche!)

int?[] test = new int?[] {0,1,2,3,4,5,6 }; int?[] t = new int?[test.Length]; t = test.Skip(1).ToArray(); t[t.Length - 1] = null;

En el espíritu de seguir usando Skip (no me preguntes, conozco el peor uso de los métodos de extensión LINQ), la única forma en que pensé en volver a escribirlo sería

int?[] test = new int?[] { 0, 1, 2, 3, 4, 5, 6 }; int?[] t = new int?[test.Length]; Array.Copy(test.Skip(1).ToArray(), t, t.Length - 1);

Pero de ninguna manera es más rápido que las otras opciones.


Si absolutamente tiene que estar en una matriz, entonces recomendaría el código más obvio posible.

for (int index = startIndex; index + 1 < values.Length; index++) values[index] = values[index + 1]; values[values.Length - 1] = null;

Esto brinda al optimizador la mayor cantidad de oportunidades para encontrar la mejor manera en cualquier plataforma de destino en la que esté instalado el programa.

EDITAR:

Acabo de pedir prestado el código de prueba de Jason Punyon, y me temo que tiene razón. Array.Copy gana!

var source = Enumerable.Range(1, 100).Cast<int?>().ToArray(); int indexToRemove = 4; var s = new Stopwatch(); s.Start(); for (int i = 0; i < 1000000; i++) { Array.Copy(source, indexToRemove + 1, source, indexToRemove, source.Length - indexToRemove - 1); //for (int index = indexToRemove; index + 1 < source.Length; index++) // source[index] = source[index + 1]; } s.Stop(); Console.WriteLine(s.Elapsed);

Array.Copy tarda entre 103 y 150 ms en mi máquina.

for loop toma entre 269 y 338 ms en mi máquina.


Use el método Array.Copy() como en

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

El Array.Copy es probablemente el camino, Microsoft quería que Array.Copy elementos de matriz ...


Para cualquier alma vertida que encuentre este hilo y esté a punto de implementar una de las respuestas mejor calificadas. Todos son basura, no estoy seguro de por qué es eso. Quizás Dested solicitó una nueva implementación de matriz al principio o algo que ahora se eliminó de la pregunta. Bueno, si simplemente desea cambiar la matriz y no necesita una nueva, vea una respuesta como la de tdaines. Y lea sobre cosas como el Buffer Circular / Ring Buffer: http://en.wikipedia.org/wiki/Circular_buffer . No es necesario mover los datos reales. El rendimiento del desplazamiento de una matriz no debe estar vinculado al tamaño de la matriz.


Sé que esta es una vieja pregunta, pero viniendo de Google no había un ejemplo simple, así que gracias a esto es la forma más fácil de reordenar una lista, y no es necesario que proporciones el tipo que funcionará en tiempo de ejecución.

private static List<T> reorderList<T>(List<T> list){ List<T> newList = new List<T>(); list.ForEach(delegate(T item) { newList.Add(item); }); return newList; }


¡Prueba esto! usando Linq. No hay necesidad de una segunda matriz.

var i_array = new int?[] {0, 1, 2, 3, 4, 5, 6 }; i_array = i_array.Select((v, k) => new { v = v, k = k }). Where(i => i.k > 0).Select(i => i.v).ToArray(); Array.Resize(ref i_array, i_array.Length + 1);

Salida: [0,1,2,3,4,5,6] se convertiría en [1,2,3,4,5,6, nulo]


Si posee memoria, podría considerar usar el código no seguro y los indicadores antiguos.

Hazte una secuencia de memoria y Marshal.AllocHGlobal o usa Marshal.AllocHGlobal Construye todas tus matrices con un poco de relleno al principio y al final. incrementar o disminuir todos los punteros de matriz a la vez. Todavía tendrá que regresar y establecer sus valores nulos.

Si necesita incrementar o disminuir selectivamente las matrices, debería agregar relleno entre ellas.

Las matrices son estructuras de datos de nivel increíblemente bajo, si las trata de una manera de bajo nivel, puede obtener un gran rendimiento de ellas.

Un baytrail haciendo esto podría superar a Jason con toda su copia 8 Core Intel Xeon E5450 @ 3.00GHz


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; } } }


No se probó este código, pero debería desplazar todos los valores a la derecha por uno. Tenga en cuenta que las últimas tres líneas de código son todo lo que necesita para cambiar la matriz de manera eficiente.

public class Shift : MonoBehaviour { //Initialize Array public int[] queue; void Start () { //Create Array Rows queue = new int[5]; //Set Values to 1,2,3,4,5 for (int i=0; i<5;i++) { queue[i] = i + 1; } //Get the integer at the first index int prev = queue[0]; //Copy the array to the new array. System.Array.Copy(queue, 1, queue, 0, queue.Length - 1); //Set the last shifted value to the previously first value. queue[queue.Length - 1] = prev;


Vea el código de C # a continuación para eliminar el espacio de la cadena. Ese personaje de cambio en conjunto. El rendimiento es O (n). No se usa ninguna otra matriz. Así que no hay memoria extra tampoco.

static void Main(string[] args) { string strIn = System.Console.ReadLine(); char[] chraryIn = strIn.ToCharArray(); int iShift = 0; char chrTemp; for (int i = 0; i < chraryIn.Length; ++i) { if (i > 0) { chrTemp = chraryIn[i]; chraryIn[i - iShift] = chrTemp; chraryIn[i] = chraryIn[i - iShift]; } if (chraryIn[i] == '' '') iShift++; if (i >= chraryIn.Length - 1 - iShift) chraryIn[i] = '' ''; } System.Console.WriteLine(new string(chraryIn)); System.Console.Read(); }


El mejor y más eficiente método creo que está usando la función Buffer.BlockCopy. Establecerá tanto el origen como el destino en su matriz, el desplazamiento de la fuente es 1. Dependiendo de su tipo de matriz (supongo que es int), 1 int = 4 bytes, por lo que debe pasar 4 como el segundo parámetro de este función. Tenga en cuenta que el desplazamiento es el desplazamiento de bytes.

Entonces se ve así:

int bytes2copy = yourArray.length - 4; Buffer.BlockCopy(yourArray, 4, yourArray, 0, bytes2copy); yourArray[yourArray.length-1] = null;