按模数排序 [英] Sorting with a modulus

查看:78
本文介绍了按模数排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用uksort将列表分类为列.

I am trying trying to sort a list into columns with uksort.

该数组已经按字母顺序排序,因此就像array('A','B','C','D','E','F','G','H','I','J','K','L','M')

The array already alpha sorted, so it is like array('A','B','C','D','E','F','G','H','I','J','K','L','M')

哪些内容以html形式显示为浮动元素:

Which gets displayed in html, as floated elements:

A B C D
E F G H
I J K L
M

我希望它重新排序,以便显示如下:

I want it reordered so it displays like this:

A E H K
B F I L
C G J M
D

所以排序后的数组将是:array('A','E','H','K','B','F','I','L','C','G','J','M','D'

So the sorted array would be: array('A','E','H','K','B','F','I','L','C','G','J','M','D'

基本上,与按字母顺序对列表进行模排序但对于php.我试过采用javascript的解决方案,并将其转换为php,但是我没有得到正确的解决方案.任何人都有关于如何在php中执行此操作的想法吗?

Basically, the same as Sorting a list alphabetically with a modulus but for php. I've tried taking the solution for javascript and convert it into php, but I'm not getting something right. Anyone have any ideas of how to do this in php?

这是我尝试过的:

function cmp_nav_by4($a, $b) {
    if (($a % 5) < ($b % 5)) {
        return 1;
    } elseif (($a % 4) > ($b % 4)) {
        return -1;
    } else {
        return $a < $b ? 1 : -1;
    }
}
$result = uksort($thearray, "cmp_nav_by4");

推荐答案

设置以下内容:

$array = range('A', 'M');
$columns = 4;
$length = count($array);

print_matrix($array, $columns);

根据索引(行和列)以及每个元素的顺序输出每个成员及其键:

Which outputs each member and it's key by index (row and colum) and as well the elements order on top:

One row - A B C D E F G H I J K L M
A[ 0] B[ 1] C[ 2] D[ 3] 
E[ 4] F[ 5] G[ 6] H[ 7] 
I[ 8] J[ 9] K[10] L[11] 
M[12] 

链接的javascript代码可以轻松转换为PHP.但是,如果您仔细查看该问题/答案,就会发现它仅适用于整行,就像我之前的尝试一样:

The javascript code linked could be easily converted to PHP. However, if you look closely to that question/answer, it becomes clear that it only work with full rows, like with my previous attempt:

function callback_sort($array, $columns)
{
    $sort = function($columns)
    {
        return function($a, $b) use ($columns)
        {
            $bycol = ($a % $columns) - ($b % $columns);
            return $bycol ? : $a - $b;
        };
    };

    uksort($array, $sort(4));

    return $array;
}

输出:

One row - A E I M B F J C G K D H L
A[ 0] E[ 4] I[ 8] M[12] 
B[ 1] F[ 5] J[ 9] C[ 2] 
G[ 6] K[10] D[ 3] H[ 7] 
L[11] 

所以只是另一个问题中提供的功能不起作用.

So it's just that the function provided in the other question does not work.

但是,由于数组已经排序,因此您无需再次对其进行排序,而只需更改顺序或元素即可.但是哪个命令?如果矩阵不完整,例如n x n完全填充,每列需要计算一个不同的新索引.以包含13个元素(A-M)的示例为例,您每列的行分布如下:

But as the array is already sorted, you don't need to sort it again but just to change the order or elements. But which order? If the matrix is not complete e.g. n x n fully filled, per each column, a different new index needs to be calculated. Taken the example with 13 elements (A-M) gives you the following distribution of rows per column:

column: 1 2 3 4
rows:   4 3 3 3

因此,每一列的值都不同.例如,在索引12处,第13个元素在第4行中.在到达该位置的途中,它已通过第1列4次,在其他2-4列中3次.因此,要获得迭代索引的虚拟索引,您需要对每个列的访问频率求和,以求出原始索引中有多少个数字.如果您超过了最大成员数,则继续从0开始.

So per each column, the value differs. For example at index 12, the 13th element is in the 4th row. On the way coming to that position, it has been passed 4 times through column 1 and 3 times in the other columns 2-4. So to get the virtual index of the iterated index, you need so sum how often you've been in each column to find out how many numbers in the original index you were going forward. If you go over the maximum number of members, you continue over at 0.

因此,可以通过逐步提高每个索引来将计算分布到各个索引上来迭代地解决此问题:

So this could be iteratively solved by stepping forward per each index to distribute the calculation over the indexes:

Index 0:
    No column: 0

Index 1:
    1x in column is which has 4 rows: 4

Index 2:
    1x in column 1 (4 rows) and 1x in other columns (3 rows): 4 + 3

...等等.如果虚拟索引超过12,它将从0开始,例如,对于第5个元素(索引4),虚拟索引将计算出13:

... and so on. If the virtual index goes over 12, it will start at 0, for example for the 5th Element (index 4) the virtual index would calculate 13:

Index 4:
    1x 4 rows and 3x 3 rows = 13 (4 + 9)
    13 > 12 => 1 (13 - 12)

现在通过从虚拟索引0开始并每次给出适当的偏移量来填充新数组(查看您所在的列,添加该列的行数,必要时环绕),将给出所需的输出:

Now filling a new array by starting with the virtual index 0 and giving the appropriate offset each time (look in which column you are, add the number of rows of that column, wrap around if necessary) will give the desired output:

One row - A E H K B F I L C G J M D
A[ 0] E[ 4] H[ 7] K[10] 
B[ 1] F[ 5] I[ 8] L[11] 
C[ 2] G[ 6] J[ 9] M[12] 
D[ 3] 

用代码编写,是对原始索引的简单foreach.通过维护键的索引,它也适用于任何数组,即使是带有字符串键的数组也是如此:

Written in code, that's a simple foreach over the original indexes. By maintaining an index of keys as well, this works with any array, even those with string keys:

$floor = floor($length/$columns);
$modulo = $length % $columns;
$max = $length-1;
$virtual = 0;
$keys = array_keys($array);
$build = array();
foreach($keys as $index => $key)
{
    $vkey = $keys[$virtual];
    $build[$vkey] = $array[$vkey];
    $virtual += $floor + ($index % $columns < $modulo);
    ($virtual>$max) && $virtual %= $max;
}

print_matrix($build, $columns);

就是这样:演示 查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆