有没有人有一个很好的算法来重新排序一个值数组(已经预先排序),以便它们可以显示在多个(N)列中并垂直读取?这将在.Net中实现,但我更喜欢可移植的东西,而不是一些神奇的功能.
它工作的一个很好的例子是ASP.Net CheckBoxList控件呈现为一个方向设置为垂直的表.
这是输入和输出的示例:
输入:
Columns = 4
Array = {"A","B","C","D","E","F","G"}
输出:
ACEG
BDF
谢谢!
更新(更多信息):
我想我可能需要提供一些关于我正在尝试做什么的更多信息...大多数问题来自于使用CheckBoxList的自动绑定(在这里你可以指定列和方向输出,它会输出使用jQuery/AJAX创建复选框网格的正确顺序的项目表.所以我试图使用具有指定宽度的div块的css复制该布局(在已知宽度的容器div内),因此它们包裹在N个项目(或列)之后.这也可以在表格中呈现(就像ASP一样) .Net做到了.)
一切都很好,除了顺序是水平的,当你在列表中获得大量项目时,更容易阅读垂直列.
如果数组中没有足够的项来生成偶数网格,那么它应该在网格的正确行/列中输出一个空白点.
如果一个数组没有足够的项目来制作一行,那么只需按原始顺序输出一行.
其他一些输入/输出可能是:
Columns = 3
Array = {"A","B","C","D"}
ACD
B.
Columns = 5
Array = {"A","B","C","D","E","F","G","H"}
ACEGH
BDF
Columns = 5
Array = {"A","B","C","D"}
A B C D
好的,我很抱歉我的初始陈述,但是如果你希望它能像我在第一个答案的评论中描述的那样工作,你实际上需要重新排序数据......好吧.它可以在没有辅助矩阵的情况下完成,但是结果代码可能非常复杂,只要矩阵只使用几个字节的内存,为什么不使用这个小辅助器结构呢?
我的代码在下面做的是创建一个矩阵.我们从上到下,然后从左到右编写矩阵(当我们用尽元素填充第一行的所有列时,停止填充除第一行之外的任何内容).然后我们以不同的顺序,从左到右,从上到下阅读它.基本上我们在这里做的是转置矩阵,通过一次编写,但以另一种顺序阅读.转置矩阵是一种非常基本的数学运算(通过使用矩阵计算和转置的许多3D编程工作实际上是一个简单的操作).诀窍是我们最初如何填充矩阵.为了确保我们可以在任何情况下填充第一列,与所需列的数量和数组的大小无关,如果我们用完了元素并保留剩下的所有元素,我们必须按正常顺序停止填充矩阵.第一排.这将产生您在评论中建议的输出.
说实话,整个事情有点复杂,但它背后的理论应该是理智的,而且它很可爱:-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; }
输出是
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
这个C代码应该很容易移植到PHP,C#,Java等,没有大的魔力,所以它几乎是通用的,可移植的和跨平台的.
我应该补充一件重要的事情:
如果将Columns设置为零(除以零,我不检查),此代码将崩溃,但0列的含义是什么?如果你的列数多于数组中的元素,它也会崩溃,我也不会检查.获得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; }
此外,你还应该检查arraySize是否为0,在这种情况下你可以直接跳出函数,因为在这种情况下,函数绝对无关:)添加这些检查应该使代码坚如磐石.
在阵列中具有NULL元素将起作用,顺便说一句,在这种情况下,结果输出中没有空洞.只是跳过NULL元素,就像不存在一样.我们可以使用
char * Array[] = {"A", "B", "C", "D", "E", NULL, "F", "G", "H", "I"};
输出将是
ADFI BEG CH
对于列== 4.如果需要孔,则需要创建孔元素.
char hole = 0; char * Array[] = {"A", "B", &hole, "C", "D", "E", &hole, "F", "G", "H", "I"};
并稍微修改绘画代码
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");
输出样本:
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