.net - datos - Ordenar una lista en mĂșltiples columnas verticales
ordenar listbox c# (3)
Esto parece asignaciones de tarea de todos modos
array<String^>^ sArray = {"A", "B", "C", "D", "E", "F", "G"};
double Columns = 4;
double dRowCount = Convert::ToDouble(sArray->Length) / Columns;
int rowCount = (int) Math::Ceiling(dRowCount);
int i = 0;
int shift = 0;
int printed = 0;
while (printed < sArray->Length){
while (i < sArray->Length){
if (i % rowCount == shift){
Console::Write(sArray[i]);
printed++;
}
i++;
}
Console::Write("/n");
i = 0;
shift++;
}
¿Alguien tiene un buen algoritmo para reordenar una matriz de valores (ya preordenada) para que puedan mostrarse en múltiples (N) columnas y ser leídos verticalmente? Esto se implementaría en .Net, pero preferiría algo portátil y no una función mágica.
Un buen ejemplo de su funcionamiento es la representación del control ASP.Net CheckBoxList como una tabla con la dirección establecida en vertical.
Aquí hay un ejemplo de entrada y salida:
Entrada:
Columnas = 4
Array = {"A", "B", "C", "D", "E", "F", "G"}
Salida:
ACEG
BDF
¡Gracias!
Actualizado (Más información):
Creo que tendré que dar un poco más de información sobre lo que estoy tratando de hacer ... En su mayoría, este problema se produjo al pasar de utilizar un enlace automático de CheckBoxList (donde se pueden especificar las columnas y la dirección de salida y se produciría una tabla de elementos en el orden correcto) para usar jQuery / AJAX para crear la cuadrícula de casilla de verificación. Así que estoy tratando de duplicar ese diseño usando css con bloques div con anchos específicos (dentro de un contenedor div de un ancho conocido) para que se envuelvan después de N elementos (o columnas). Esto también se puede representar en una tabla (como ASP .Net lo hace.)
Todo funciona muy bien, excepto que el orden es horizontal y cuando obtienes una gran cantidad de elementos en la lista, es más fácil leer columnas verticales.
Si la matriz no tiene suficientes elementos para formar una cuadrícula par, debe generar un punto vacío en la fila / columna correcta de la cuadrícula.
Y si una matriz no tiene suficientes elementos para formar una sola fila, solo muestra los elementos en su orden original en una fila.
Alguna otra entrada / salida puede ser:
Columnas = 3
Array = {"A", "B", "C", "D"}
ACD
segundo
Columnas = 5
Array = {"A", "B", "C", "D", "E", "F", "G", "H"}
ACEGH
BDF
Columnas = 5
Array = {"A", "B", "C", "D"}
A B C D
Una pequeña ACTUALIZACIÓN:
El algoritmo que estoy usando aquí es uno modificado que usarías para pintar imágenes. Estoy fingiendo que las entradas de la matriz son datos de píxeles de una imagen y luego estoy pintando la imagen de izquierda a derecha (1. LtoR) y de arriba a abajo (2. TtoB), sin embargo, los datos de la imagen se almacenan desde de arriba abajo (1. TtoB) y luego de izquierda a derecha (2. LtoR); IOW en un orden diferente. Como una imagen no puede tener agujeros , esta es la razón por la que no funcionará con 5 o 6 columnas. Con 4 columnas, la salida es
ACEG
BDF
Como imagen, esto se ve así
OOOO
OOO.
Con O es un píxel de la imagen y. siendo un píxel indefinido (uno que falta). Los desaparecidos solo pueden estar al final de la imagen, no en el medio de ella. Eso significa que también podría verse así
OOO
OO.
OO.
OO.
Todos los píxeles faltantes están siempre al final, si lee primero de arriba a abajo y luego de izquierda a derecha, porque en ese caso todos los píxeles faltantes se siguen directamente entre sí al final. Si leo el diagrama TtoB y luego LtoR, debe decir "Pixel, Pixel, Pixel, Pixel, ..., Pixel, Missing, Missing, Missing, ..., Missing", es posible que nunca lea "Pixel, Missing, Pixel "o" Missing, Pixel, Missing ". Todos los píxeles están juntos y todas las pérdidas son, también.
Con 5 columnas, como sugiere el comentario, debería verse así
ACEFG
BD
Sin embargo, como imagen esto se vería así
OOOOO
OO...
Y esto no está permitido por el algoritmo. Si lo leo TtoB y luego LtoR, se leerá: "Pixel, Pixel, Pixel, Pixel, Pixel, Missing, Pixel, Missing, Pixel, Missing". Y como se indicó anteriormente, esto no está permitido por el algoritmo. Por lo tanto, este enfoque simple de pintura de píxeles no pintará tantas columnas como se solicite si pintar tantas columnas provoca agujeros en la imagen. En ese caso, simplemente rellenará los agujeros, sin embargo, esto hará que se dibujen menos columnas.
Déjame pensar en una solución que siempre pinta los números solicitados de píxeles (en una respuesta separada).
No es necesario reorganizar los datos en la memoria para nada. Simplemente imprímalo en el orden deseado.
Algún código C (lo estoy haciendo extremadamente detallado, para que todos entiendan lo que estoy haciendo. Por supuesto, esto puede ser mucho más compacto):
int Columns = 4;
char * Array[] = {"A", "B", "C", "D", "E", "F", "G"};
int main (
int argc,
char ** argv
) {
// This is hacky C for quickly get the number of entries
// in a static array, where size is known at compile time
int arraySize = sizeof(Array) / sizeof(Array[0]);
// How many rows are we going to paint?
int rowsToPaint = (arraySize / Columns) + 1;
int col;
int row;
for (row = 0; row < rowsToPaint; row++) {
for (col = 0; col < Columns; col++) {
int index = col * rowsToPaint + row;
if (index >= arraySize) {
// Out of bounds
continue;
}
printf("%s", Array[index]);
}
printf("/n"); // next row
}
printf("/n");
return 0;
}
Nota: Esto funciona bien con un valor de 8 (por lo que todo está pintado dentro de una fila) y valores de 4 y menos (funciona bien con 3, 2 y 1), pero no puede funcionar con 5. Esto no es culpa del algoritmo, es la culpa de la restricción.
ACEFG
BD
La restricción dice que las columnas se leen de arriba a abajo para obtener los datos ordenados corregidos. Pero arriba, " EFG " está ordenado y no está de arriba a abajo, de izquierda a derecha. Por lo tanto, este algoritmo tiene un problema. Usar Columnas = 3 funcionará
ADG
BE
CF
Usar dos funcionará también
AE
BF
CG
D
Y uno pondrá todo en una columna.
Bien, lo siento por mi declaración inicial, pero cuando quieres que funcione como lo describiste en el comentario de mi primera respuesta, de hecho necesitas reordenar los datos ... bueno, de alguna manera. Tal vez podría hacerse sin la matriz auxiliar, sin embargo, el código resultante probablemente sea muy complejo y mientras la matriz solo use un par de bytes de memoria, ¿por qué no usar esta pequeña construcción auxiliar?
Lo que hace mi código a continuación es crear una matriz. Escribimos la matriz de arriba a abajo y luego de izquierda a derecha (y dejamos de llenar todo menos la primera fila cuando nos quedamos sin elementos para llenar todas las columnas de la primera fila). Luego lo leemos en un orden diferente, de izquierda a derecha y de arriba a abajo. Básicamente, lo que hacemos aquí es transponer una matriz , escribiéndola en un orden, pero leyéndola en otro orden. La transposición de una matriz es una operación matemática muy elemental (muchos trabajos de programación 3D mediante el uso de cálculos matriciales y la transposición es en realidad una operación simple). El truco es cómo llenamos inicialmente la matriz. Para asegurarnos de que podemos llenar la primera columna en cualquier caso, independientemente del número de columnas deseadas y el tamaño de la matriz, debemos dejar de llenar la matriz en el orden normal si nos quedamos sin elementos y reservamos todos los elementos sobrantes para el primera fila. Esto producirá el resultado que ha sugerido en su comentario.
Todo es un poco complicado para ser sincero, pero la teoría detrás de esto debería ser sensata y funciona de maravilla :-D
int Columns;
char * Array[] = {"A", "B", "C", "D", "E", "F", "G"};
int main (
int argc,
char ** argv
) {
// Lets thest this with all Column sizes from 1 to 7
for (Columns = 1; Columns <= 7; Columns++) {
printf("Output when Columns is set to %d/n", Columns);
// This is hacky C for quickly get the number of entries
// in a static array, where size is known at compile time
int arraySize = sizeof(Array) / sizeof(Array[0]);
// How many rows we will have
int rows = arraySize / Columns;
// Below code is the same as (arraySize % Columns != 0), but
// it''s almost always faster
if (Columns * rows != arraySize) {
// We might have lost one row by implicit rounding
// performed for integer division
rows++;
}
// Now we create a matrix large enough for rows * Columns
// references. Note that this array could be larger than arraySize!
char ** matrix = malloc(sizeof(char *) * rows * Columns);
// Something you only need in C, C# and Java do this automatically:
// Set all elements in the matrix to NULL(null) references
memset(matrix, 0, sizeof(char *) * rows * Columns );
// We fill up the matrix from top to bottom and then from
// left to right; the order how we fill it up is very important
int matrixX;
int matrixY;
int index = 0;
for (matrixX = 0; matrixX < Columns; matrixX++) {
for (matrixY = 0; matrixY < rows; matrixY++) {
// In case we just have enough elements left to only
// fill up the first row of the matrix and we are not
// in this first row, do nothing.
if (arraySize + matrixX + 1 - (index + Columns) == 0 &&
matrixY != 0) {
continue;
}
// We just copy the next element normally
matrix[matrixY + matrixX * rows] = Array[index];
index++;
//arraySize--;
}
}
// Print the matrix exactly like you''d expect a matrix to be
// printed to screen, that is from left to right and top to bottom;
// Note: That is not the order how we have written it,
// watch the order of the for-loops!
for (matrixY = 0; matrixY < rows; matrixY++) {
for (matrixX = 0; matrixX < Columns; matrixX++) {
// Skip over unset references
if (matrix[matrixY + matrixX * rows] == NULL)
continue;
printf("%s", matrix[matrixY + matrixX * rows]);
}
// Next row in output
printf("/n");
}
printf("/n");
// Free up unused memory
free(matrix);
}
return 0;
}
La salida es
Output when Columns is set to 1
A
B
C
D
E
F
G
Output when Columns is set to 2
AE
BF
CG
D
Output when Columns is set to 3
ADG
BE
CF
Output when Columns is set to 4
ACEG
BDF
Output when Columns is set to 5
ACEFG
BD
Output when Columns is set to 6
ACDEFG
B
Output when Columns is set to 7
ABCDEFG
Este código C debe ser fácil de portar a PHP, C #, Java, etc., no se trata de una gran magia, por lo que es prácticamente universal, portátil y multiplataforma.
Una cosa importante que debería agregar:
Este código se bloqueará si configura Columnas en cero (división por cero, no lo compruebo), pero ¿qué sentido tendrían las 0 Columnas? Y también se bloqueará si tienes más columnas que elementos en la matriz, tampoco lo compruebo. Puede verificar fácilmente para inmediatamente después de obtener el arraySize:
if (Columns <= 0) {
// Having no column make no sense, we need at least one!
Columns = 1;
} else if (Columns > arraySize) {
// We can''t have more columns than elements in the array!
Columns = arraySize;
}
Además, debe verificar que arraySize sea 0, en cuyo caso puede saltar directamente de la función, ya que en ese caso no hay absolutamente nada que hacer para la función :) Agregar estos controles debería hacer que el código sea sólido.
Tener elementos NULL en la matriz funcionará, por cierto, en ese caso no hay agujeros en la salida resultante. Los elementos NULL simplemente se saltan como si no estuvieran presentes. Eg permite el uso
char * Array[] = {"A", "B", "C", "D", "E", NULL, "F", "G", "H", "I"};
La salida será
ADFI
BEG
CH
para Columnas == 4. Si quieres agujeros , necesitas crear un elemento de agujero.
char hole = 0;
char * Array[] = {"A", "B", &hole, "C", "D", "E", &hole, "F", "G", "H", "I"};
y modificar el código de pintura un poco
for (matrixY = 0; matrixY < rows; matrixY++) {
for (matrixX = 0; matrixX < Columns; matrixX++) {
// Skip over unset references
if (matrix[matrixY + matrixX * rows] == NULL)
continue;
if (matrix[matrixY + matrixX * rows] == &hole) {
printf(" ");
} else {
printf("%s", matrix[matrixY + matrixX * rows]);
}
}
// Next row in output
printf("/n");
}
printf("/n");
Muestras de salida:
Output when Columns is set to 2
A
BF
G
CH
DI
E
Output when Columns is set to 3
ADG
BEH
I
CF
Output when Columns is set to 4
AC H
BDFI
EG