4

uksortを使用してリストを列に並べ替えようとしています。

配列はすでにアルファソートされているので、次のようになりますarray('A','B','C','D','E','F','G','H','I','J','K','L','M')

これは、浮動要素としてhtmlに表示されます。

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

次のように表示されるように並べ替えます。

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'

基本的に、モジュラスを使用してリストをアルファベット順に並べ替えるのと同じですが、php用です。javascriptのソリューションを使用して、それをphpに変換しようとしましたが、うまくいきません。誰もが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");
4

2 に答える 2

6

以下を設定します。

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

print_matrix($array, $columns);

これは、各メンバーとそのキーをインデックス(行と列)で出力し、要素の順序も上に表示されます。

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に変換できます。ただし、その質問/回答をよく見ると、以前の試みのように、完全な行でのみ機能することが明らかになります。

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] 

したがって、他の質問で提供されている機能が機能しないというだけです。

ただし、配列はすでに並べ替えられているため、並べ替える必要はなく、順序や要素を変更するだけです。しかし、どの順序ですか?マトリックスが完全でない場合、たとえばn x n完全に塗りつぶされている場合は、列ごとに、異なる新しいインデックスを計算する必要があります。13個の要素(A-M)を使用した例では、列ごとに次の行の分布が得られます。

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

したがって、列ごとに値が異なります。たとえば、インデックス12では、13番目の要素が4行目にあります。その位置に到達する途中で、列1を4回通過し、他の列2〜4を3回通過しました。したがって、反復インデックスの仮想インデックスを取得するには、各列にアクセスした頻度を合計して、元のインデックスに含まれる数値の数を調べる必要があります。メンバーの最大数を超えると、0から続行します。

したがって、これは、各インデックスごとに前進して計算をインデックス全体に分散することで、繰り返し解決できます。

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を計算します。

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

ここで、仮想インデックスから始めて、0毎回適切なオフセットを指定して新しい配列を埋めます(現在の列を確認し、その列の行数を追加し、必要に応じて折り返します)。目的の出力が得られます。

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ので、元のインデックスよりも単純です。キーのインデックスも維持することにより、これは、文字列キーを持つ配列であっても、すべての配列で機能します。

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

そしてそれはそれです:デモ要点

于 2012-02-25T15:56:48.853 に答える
1

@hakreには正しいコードの答えがあります。理由:

基になるソート関数Zend_qsortは、実際には要素とキーを並べ替えません。代わりに、zendエンジンが使用する内部配列バケットを並べ替えます。数値インデックス付き配列をksortする場合は、それを繰り返し処理すると$q = count($array);for($i=0; $i<$q); $i++) 、以前とまったく同じ値が返されます。繰り返し処理するとfor($key in $array)、新しいキーの順序が取得されます。

于 2012-02-25T23:05:29.577 に答える