有没有人有一个很好的算法来重新排序一个值数组(已经预先排序),以便它们可以显示在多个(N)列中并可以垂直读取?这将在.Net中实现,但我更喜欢便携式而不是一些神奇的功能。
它工作的一个很好的例子是ASP.Net CheckBoxList控件呈现为一个方向设置为垂直的表。
以下是输入和输出的示例:
输入:
列= 4
Array = {“A”,“B”,“C”,“D”,“E”,“F”,“G”}
输出:
交流励磁发电机
BDF
谢谢!
更新(更多信息):
我想我可能需要提供一些关于我正在尝试做什么的更多信息...大多数问题来自于使用CheckBoxList的自动绑定(您可以在其中指定列和方向输出和它将以正确的顺序输出项目表),以使用jQuery / AJAX创建复选框网格。所以我试图使用具有指定宽度的div块的css复制该布局(在已知宽度的容器div内),因此它们包裹在N个项目(或列)之后。这也可以在表格中呈现(就像ASP一样) .Net做到了。)
一切都很有效,除了订单是水平的,当你在列表中获得大量项目时,更容易阅读垂直列。
如果数组中没有足够的项目来制作偶数网格,那么它应该在网格的正确行/列中输出一个空白点。
如果一个数组没有足够的项目来制作一行,那么只需按原始顺序输出一行。
其他一些输入/输出可能是:
列= 3
Array = {“A”,“B”,“C”,“D”}
ACD
乙
列= 5
Array = {“A”,“B”,“C”,“D”,“E”,“F”,“G”,“H”}
ACEGH
BDF
列= 5
Array = {“A”,“B”,“C”,“D”}
ABCD
答案 0 :(得分:6)
好的,我很抱歉我的初步陈述,但是当你希望它按照我在第一个答案的评论中描述的那样工作时,你实际上需要对数据进行重新排序......好吧。它可以在没有辅助矩阵的情况下完成,但是结果代码可能非常复杂,只要矩阵只使用几个字节的内存,为什么不使用这个小帮助器构造?
我的代码在下面创建了一个矩阵。我们从上到下,然后从左到右编写矩阵(当我们用尽元素填充第一行的所有列时,停止填充除第一行之外的任何内容)。然后我们以不同的顺序,从左到右,从上到下阅读它。基本上我们在这里做的是transposing a matrix,通过一个顺序写它,但是以另一个顺序读它。转置矩阵是一种非常基本的数学运算(通过使用矩阵计算和转置的许多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
答案 1 :(得分:2)
我在这里使用的算法是一个用于绘制图像的修改过的算法。我假装数组条目是图像的像素数据,然后我从左到右(1.LtoR)和从上到下(2.TtoB)绘制图像,但是,图像数据是从从上到下(1.TtoB)然后从左到右(2.LtoR); IOW以不同的顺序。由于图像不能有 hole ,这就是为什么它不适用于5或6列的原因。有4列输出
ACEG
BDF
作为图像,这看起来像这样
OOOO
OOO.
O是图像的像素。是一个未定义的像素(缺少一个)。缺失的可能只在图像的末尾,而不是在图像的中间。这意味着它也可能看起来像这样
OOO
OO.
OO.
OO.
如果您从上到下阅读第一个而从左到右阅读然后,则所有丢失的像素总是在最后,因为在这种情况下,所有丢失的像素都会直接跟随最后彼此。如果我读图TtoB然后读LtoR,它必须读起来像“Pixel,Pixel,Pixel,Pixel,...,Pixel,Missing,Missing,Missing,...,Missing”,它可能永远不会读到“Pixel,缺少,像素“或”缺失,像素,缺失“。所有像素都在一起,所有缺失都是。
有5列,如评论所示,它应该看起来像这样
ACEFG
BD
然而,作为图像,这将是这样的
OOOOO
OO...
算法不允许这样做。如果我读它TtoB然后读LtoR,它会读到:“Pixel,Pixel,Pixel,Pixel,Pixel,Missing,Pixel,Missing,Pixel,Missing”。如上所述,算法不允许这样做。因此,如果绘制许多列导致图像中的孔,则这种简单的像素绘制方法将不会绘制所需的列数。在这种情况下,它只会填满空洞,但这会导致绘制较少的列。
让我想一个总是绘制所需像素数的解决方案(在单独的回复中)。
您根本不需要在内存中重新排列数据。只需按所需顺序打印即可。
一些C代码(我这样做非常冗长,所以每个人都明白我在做什么。当然这可以更加紧凑):
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;
}
注意:这可以正常工作,值为8(因此所有内容都在一行中绘制),值为4及以下(适用于3,2和1),但它不适用于5.这是不是算法的错,它是约束的错。
ACEFG
BD
约束表示从上到下读取列以获取更正的排序数据。但是上面的“ EFG ”是排序的,它不是从上到下,而是从左到右。因此该算法存在问题。使用Columns = 3将起作用
ADG
BE
CF
使用两个也可以使用
AE
BF
CG
D
人们会将所有内容放在一列中。
答案 2 :(得分:1)
这看起来像家庭作业 反正
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++;
}