php中的小型排序算法

发布于 2024-12-10 15:29:38 字数 1978 浏览 0 评论 0原文

它应该是非常简单的算法,但我就是无法绕过它。

我有一些按字母顺序排列的数组

[0] => Array
    (
        [0] => a
        [1] => b
        [2] => c
    )

,例如

[0] => Array
    (
        [0] => a
        [1] => b
        [2] => c
        [3] => d
    )

,我需要将它们排序为行。例如:

我应该收到一个包含 3 列和尽可能多的行的表,并且应该按字母顺序排列。

这是一个例子: 第一个数组应该转换为

[0] => Array
    (
        [0] => Array
            (
                [0] => a
                [1] => b
                [2] => c
            )

    )

但第二个数组应该是

[1] => Array
    (
        [0] => Array
            (
                [0] => a
                [1] => c
                [2] => d
            )
        [1] => Array
            (
                [0] => b
            )
    )

我在 php 中编写的,所以如果有人可以帮助我,我将非常感激。

UPD: 代码示例:

function sortAsOrdered( array $categories )
{
    foreach ( $categories as $groupId => $group )
    {
        $regroupMenuItems = array();
        $limit            = count( $group );
        $rows             = ceil( $limit / 3 );

        for ( $i = 0; $i < $rows; ++$i )
        {
            $jumper = 0;

            for ( $j = 0; $j < 3; $j++ )
            {
                if ( 0 == $jumper )
                {
                    $jumper = $i;
                }

                if ( isset( $group[ $jumper ] ) )
                {
                    $regroupMenuItems[ $i ][ $j ] = $group[ $jumper ];
                }

                $jumper = $jumper + $rows;
            }
        }

        $categories[ $groupId ] = $regroupMenuItems;
    }

    return $categories;
}

伙计们,我解决了这个问题。在这里你可以看到我的算法http://pastebin.com/xe2yjhYW。 但不要悲伤,你的帮助不会白费。我可能只会为那些帮助我完成这个困难算法的人提供赏金。

伙计们再次感谢。你的想法激励我以不同的方式思考。

It should quite simple algorithm, but I just can't get around it.

I have some arrays in alphabetical order

[0] => Array
    (
        [0] => a
        [1] => b
        [2] => c
    )

and for example

[0] => Array
    (
        [0] => a
        [1] => b
        [2] => c
        [3] => d
    )

and I need to sort them into rows. For example:

I should receive a table with 3 columns and as many rows as it may get and it should be in alphabetical order.

Here is an example:
First array should be converted into

[0] => Array
    (
        [0] => Array
            (
                [0] => a
                [1] => b
                [2] => c
            )

    )

But second one should be as

[1] => Array
    (
        [0] => Array
            (
                [0] => a
                [1] => c
                [2] => d
            )
        [1] => Array
            (
                [0] => b
            )
    )

I'm writing it in php, so if anyone can help I would be really appreciated.

UPD:
Code example:

function sortAsOrdered( array $categories )
{
    foreach ( $categories as $groupId => $group )
    {
        $regroupMenuItems = array();
        $limit            = count( $group );
        $rows             = ceil( $limit / 3 );

        for ( $i = 0; $i < $rows; ++$i )
        {
            $jumper = 0;

            for ( $j = 0; $j < 3; $j++ )
            {
                if ( 0 == $jumper )
                {
                    $jumper = $i;
                }

                if ( isset( $group[ $jumper ] ) )
                {
                    $regroupMenuItems[ $i ][ $j ] = $group[ $jumper ];
                }

                $jumper = $jumper + $rows;
            }
        }

        $categories[ $groupId ] = $regroupMenuItems;
    }

    return $categories;
}

Guys I solved this one. Here you could see my algorithm http://pastebin.com/xe2yjhYW.
But don't be sad your help will not go in vain. I probably will place bounty just for those who helped with this dificult algorithm for me.

Guys thanks one more time. Your thoughts inspired me to think differently.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

从﹋此江山别 2024-12-17 15:29:39

array_chunk 是解决该问题的自然第一种方法,但它并不能完全满足您的需要。如果以这种方式提供解决方案,则需要在处理之前重新构造结果数组或重新构造输入,如下所示:

$input = range('a', 'k');  // arbitrary
$columns = 3;  // configure this
$rows = ceil(count($input) / $columns);

// fugly, but this way it works without declaring a function
// and also in PHP < 5.3 (on 5.3 you'd use a lambda instead)
$order = create_function('$i',
                         '$row = (int)($i / '.$rows.');'.
                         '$col = $i % '.$rows.';'.
                         'return $col * ('.$columns.' + 1) + $row;');

// $order is designed to get the index of an item in the original array,
// and produce the index that item would have if the items appeared in
// column-major order instead of row-major as they appear now
$array = array_map($order, array_keys($input));

// replace the old keys with the new ones
$array = array_combine($array, $input);

// sort based on the new keys; this will effectively transpose the matrix,
// if it were already structured as a matrix instead of a single-dimensional array
ksort($array);

// done!
$array = array_chunk($array, $columns);
print_r($array);

查看实际情况

array_chunk is a natural first approach to the problem, but it won't do exactly what you need to. If the solution is provided that way, you need to either restructure the resulting array or restructure the input before processing it, as below:

$input = range('a', 'k');  // arbitrary
$columns = 3;  // configure this
$rows = ceil(count($input) / $columns);

// fugly, but this way it works without declaring a function
// and also in PHP < 5.3 (on 5.3 you'd use a lambda instead)
$order = create_function('$i',
                         '$row = (int)($i / '.$rows.');'.
                         '$col = $i % '.$rows.';'.
                         'return $col * ('.$columns.' + 1) + $row;');

// $order is designed to get the index of an item in the original array,
// and produce the index that item would have if the items appeared in
// column-major order instead of row-major as they appear now
$array = array_map($order, array_keys($input));

// replace the old keys with the new ones
$array = array_combine($array, $input);

// sort based on the new keys; this will effectively transpose the matrix,
// if it were already structured as a matrix instead of a single-dimensional array
ksort($array);

// done!
$array = array_chunk($array, $columns);
print_r($array);

See it in action.

动次打次papapa 2024-12-17 15:29:39

让我们看看这是否更接近标记

function splitVerticalArrayIntoColumns($aInput, $iNumberOfColumns) {

  //output array
  $aOutput = array();

  //the total length of the input array
  $iInputLength = count($aInput);
  
  //the number of rows will be ceil($iInputLength / $iNumberOfColumns)
  $iNumRows = ceil($iInputLength / $iNumberOfColumns);
  
  for($iInputIndex = 0; $iInputIndex < $iInputLength; $iInputIndex++) {
    $iCurrentRow = $iInputIndex % $iNumRows;
    $aOutput[$iCurrentRow][] = $aInput[$iInputIndex];
  }

  //return
  return $aOutput;
}

哪个 - 当这样运行时:

$aList = array("a", "e", "d", "b", "c");
echo 'array("a", "e", "d", "b", "c")' . "\n\n";
print_r(splitVerticalArrayIntoColumns($aList, 3));

给出:

array("a", "e", "d", "b", "c")

Array
(
    [0] => Array
        (
            [0] => a
            [1] => d
            [2] => c
        )

    [1] => Array
        (
            [0] => e
            [1] => b
        )

)

这还没有对每一行进行排序,但这就是您想要的东西吗?



开始facepalm编辑

...或者当然,array_chunk($aList, 3)在你排序后O_o

https://www.php.net/manual/en/function.array-chunk.php

我会留下以下所有内容以供参考或其他 -我完全忘记了 array_chunk()

endfacepalm edit


我会在循环中使用模数,在其中计算数组索引(对数组进行排序后) - 例如,如果您尝试要将数组分成 3 个“列”,您可以尝试以下操作:

if($iIndex % 3 == 0) {
  //... create a new array
}
else {
  //... add to an existing array
}

编辑代码示例:

$aList = array("a", "e", "d", "b", "c");
sort($aList);

$iDesiredNumberOfColumns = 3;
$iListLength = count($aList);

$aListInColumns = array();
$iRowNumber = 0;

for($iIndex = 0; $iIndex < $iListLength; $iIndex++) {
  $iColumnNumber = $iIndex % 3;
  if($iIndex != 0 && $iColumnNumber == 0) {
    $iRowNumber++;
  }

  $aListInColumns[$iRowNumber][$iColumnNumber] = $aList[$iIndex];
}

只需在我的本地服务器上运行它(并更正拼写错误),它的输出为:

Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
            [2] => c
        )

    [1] => Array
        (
            [0] => d
            [1] => e
        )

)

可能有一种更简洁的方法(即有点程序化)但它应该可以完成工作。

Let's see if this is nearer the mark

function splitVerticalArrayIntoColumns($aInput, $iNumberOfColumns) {

  //output array
  $aOutput = array();

  //the total length of the input array
  $iInputLength = count($aInput);
  
  //the number of rows will be ceil($iInputLength / $iNumberOfColumns)
  $iNumRows = ceil($iInputLength / $iNumberOfColumns);
  
  for($iInputIndex = 0; $iInputIndex < $iInputLength; $iInputIndex++) {
    $iCurrentRow = $iInputIndex % $iNumRows;
    $aOutput[$iCurrentRow][] = $aInput[$iInputIndex];
  }

  //return
  return $aOutput;
}

Which - when run thus:

$aList = array("a", "e", "d", "b", "c");
echo 'array("a", "e", "d", "b", "c")' . "\n\n";
print_r(splitVerticalArrayIntoColumns($aList, 3));

Gives:

array("a", "e", "d", "b", "c")

Array
(
    [0] => Array
        (
            [0] => a
            [1] => d
            [2] => c
        )

    [1] => Array
        (
            [0] => e
            [1] => b
        )

)

That's not sorting each row yet but is that the kind of thing you're after?



begin facepalm edit

... or of course, array_chunk($aList, 3) after you've sorted it O_o

https://www.php.net/manual/en/function.array-chunk.php

I'll leave everything below for reference or whatever - I'd completely forgotten about array_chunk()

end facepalm edit


I'd use a modulo in a loop where you're counting the array index (after sorting the array) - for instance if you're trying to split an array into 3 "columns" you could try something like:

if($iIndex % 3 == 0) {
  //... create a new array
}
else {
  //... add to an existing array
}

EDIT code example:

$aList = array("a", "e", "d", "b", "c");
sort($aList);

$iDesiredNumberOfColumns = 3;
$iListLength = count($aList);

$aListInColumns = array();
$iRowNumber = 0;

for($iIndex = 0; $iIndex < $iListLength; $iIndex++) {
  $iColumnNumber = $iIndex % 3;
  if($iIndex != 0 && $iColumnNumber == 0) {
    $iRowNumber++;
  }

  $aListInColumns[$iRowNumber][$iColumnNumber] = $aList[$iIndex];
}

Just ran it on my local server (and corrected the typo), and it outputs as:

Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
            [2] => c
        )

    [1] => Array
        (
            [0] => d
            [1] => e
        )

)

There's probably a tidier way of doing it (that's a little procedural) but it should do the job.

失眠症患者 2024-12-17 15:29:39

怎么样:

$arrs = array(
    array('a','b','c'),
    array('a','b','c','d'),
    array('a','b','c','d','e'),
    array('a','b','c','d','e','f'),
    array('a','b','c','d','e','f','g')
);
$nbcols = 3;
foreach ($arrs as $arr) {
    $arr_size = count($arr);
    $nblines = ceil($arr_size/$nbcols);
    $res = array();
    $l = 0;
    foreach ($arr as $el) {
        if ($l == $arr_size - 1 && count($res[0]) < $nbcols) $l=0;
        $res[$l%$nblines][] = $el;
        $l++;
    }
    print_r($res);
}

输出:

Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
            [2] => c
        )

)
Array
(
    [0] => Array
        (
            [0] => a
            [1] => c
            [2] => d
        )

    [1] => Array
        (
            [0] => b
        )

)
Array
(
    [0] => Array
        (
            [0] => a
            [1] => c
            [2] => e
        )

    [1] => Array
        (
            [0] => b
            [1] => d
        )

)
Array
(
    [0] => Array
        (
            [0] => a
            [1] => c
            [2] => e
        )

    [1] => Array
        (
            [0] => b
            [1] => d
            [2] => f
        )

)
Array
(
    [0] => Array
        (
            [0] => a
            [1] => d
            [2] => g
        )

    [1] => Array
        (
            [0] => b
            [1] => e
        )

    [2] => Array
        (
            [0] => c
            [1] => f
        )

)

How about:

$arrs = array(
    array('a','b','c'),
    array('a','b','c','d'),
    array('a','b','c','d','e'),
    array('a','b','c','d','e','f'),
    array('a','b','c','d','e','f','g')
);
$nbcols = 3;
foreach ($arrs as $arr) {
    $arr_size = count($arr);
    $nblines = ceil($arr_size/$nbcols);
    $res = array();
    $l = 0;
    foreach ($arr as $el) {
        if ($l == $arr_size - 1 && count($res[0]) < $nbcols) $l=0;
        $res[$l%$nblines][] = $el;
        $l++;
    }
    print_r($res);
}

output:

Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
            [2] => c
        )

)
Array
(
    [0] => Array
        (
            [0] => a
            [1] => c
            [2] => d
        )

    [1] => Array
        (
            [0] => b
        )

)
Array
(
    [0] => Array
        (
            [0] => a
            [1] => c
            [2] => e
        )

    [1] => Array
        (
            [0] => b
            [1] => d
        )

)
Array
(
    [0] => Array
        (
            [0] => a
            [1] => c
            [2] => e
        )

    [1] => Array
        (
            [0] => b
            [1] => d
            [2] => f
        )

)
Array
(
    [0] => Array
        (
            [0] => a
            [1] => d
            [2] => g
        )

    [1] => Array
        (
            [0] => b
            [1] => e
        )

    [2] => Array
        (
            [0] => c
            [1] => f
        )

)
孤檠 2024-12-17 15:29:39

为此,您需要执行两个操作:

首先,将数组尽可能均匀地分成 3 组。

function array_grouped($arr, $group_count)
{
    if (!count($arr)) return array();
    $result = array();
    for ($i = $group_count; $i > 0; --$i)
    {
        # break off the next ceil(remaining count / remaining columns) elements
        # (avoiding FP math, cause that way lies madness)
        $result[] = array_splice($arr, 0, ((count($arr)-1) / $i) + 1);
    }
    return $result;
}

然后,“转置”数组,以便行和列交换位置。

function array_transposed($arr)
{
    $result = array();
    foreach ($arr as $x => $subarr)
    {
        foreach ($subarr as $y => $val)
        {
            if (!isset($result[$y])) $result[$y] = array();
            $result[$y][$x] = $val;
        }
    }
    return $result;
}

array_transpose(array_grouped($arr, 3)) 按您想要的顺序提供条目。

In order to do this, you need to do two operations:

First, split the array into 3 groups, as evenly as possible.

function array_grouped($arr, $group_count)
{
    if (!count($arr)) return array();
    $result = array();
    for ($i = $group_count; $i > 0; --$i)
    {
        # break off the next ceil(remaining count / remaining columns) elements
        # (avoiding FP math, cause that way lies madness)
        $result[] = array_splice($arr, 0, ((count($arr)-1) / $i) + 1);
    }
    return $result;
}

Then, "transpose" the array, so that rows and columns switch places.

function array_transposed($arr)
{
    $result = array();
    foreach ($arr as $x => $subarr)
    {
        foreach ($subarr as $y => $val)
        {
            if (!isset($result[$y])) $result[$y] = array();
            $result[$y][$x] = $val;
        }
    }
    return $result;
}

array_transposed(array_grouped($arr, 3)) gives you entries in the order you want them.

玩物 2024-12-17 15:29:39

耶耶耶!我明白了。如果您经常这样做,您可以将其变成一个函数。

# Here we setup our array and the number of columns we want.
$myArray = range('a','d');  
$numCols = 3;

# Here we break ourselves up into columns
for ($i = 0; $i < $numCols; $i++) {
    $numRows = ceil(count($myArray) / ($numCols - $i));
    $columns[$i] = array_slice($myArray,0,$numRows);
    $myArray = array_slice($myArray,$numRows);
}

# Here we transpose our array to be in rows instead of columns.
for ($i = 0; $i < $numCols; $i++) {
    for ($j = 0; $j < count($columns[$i]); $j++) {
        $rows[$j][$i] = $columns[$i][$j];
    }
}

# Our rows are now in $rows
var_dump($rows);

其输出是:

array(2) {
  [0]=>
  array(3) {
    [0]=>
    string(1) "a"
    [1]=>
    string(1) "c"
    [2]=>
    string(1) "d"
  }
  [1]=>
  array(1) {
    [0]=>
    string(1) "b"
  }
}

YAYAYAY!! I've got it. You could turn this into a function if you'll be doing it regularly.

# Here we setup our array and the number of columns we want.
$myArray = range('a','d');  
$numCols = 3;

# Here we break ourselves up into columns
for ($i = 0; $i < $numCols; $i++) {
    $numRows = ceil(count($myArray) / ($numCols - $i));
    $columns[$i] = array_slice($myArray,0,$numRows);
    $myArray = array_slice($myArray,$numRows);
}

# Here we transpose our array to be in rows instead of columns.
for ($i = 0; $i < $numCols; $i++) {
    for ($j = 0; $j < count($columns[$i]); $j++) {
        $rows[$j][$i] = $columns[$i][$j];
    }
}

# Our rows are now in $rows
var_dump($rows);

The output from this is:

array(2) {
  [0]=>
  array(3) {
    [0]=>
    string(1) "a"
    [1]=>
    string(1) "c"
    [2]=>
    string(1) "d"
  }
  [1]=>
  array(1) {
    [0]=>
    string(1) "b"
  }
}
烟花肆意 2024-12-17 15:29:39

如果简单地说,那么这里是该算法的一个方法。

/**
 * @param array $toTransform
 * @param int $columnsMax
 * @return array
 */
private function transformation( array $toTransform, $columnsMax = 3 )
{
    // First divide array as you need
    $listlen   = count( $toTransform );
    $partlen   = floor( $listlen / $columnsMax );
    $partrem   = $listlen % $columnsMax;
    $partition = array();
    $mark      = 0;

    for ( $px = 0; $px < $columnsMax; $px++ )
    {
        $incr             = ( $px < $partrem ) ? $partlen + 1 : $partlen;
        $partition[ $px ] = array_slice( $toTransform, $mark, $incr );
        $mark             += $incr;
    }

    // Secondly fill empty slots for easy template use
    $result = array();

    for ( $i = 0; $i < count( $partition[0] ); $i++ )
    {
        $tmp = array();

        foreach ( $partition as $column )
        {
            if ( isset( $column[ $i ] ) )
            {
                $tmp[] = $column[ $i ];
            }
            else
            {
                $tmp[] = '';
            }
        }

        $result[] = $tmp;
    }

    return $result;
}

我还为此添加了 PHPUnit 测试。您可以在链接中找到它。

If to say it shortly, then here is a method for that algorithm.

/**
 * @param array $toTransform
 * @param int $columnsMax
 * @return array
 */
private function transformation( array $toTransform, $columnsMax = 3 )
{
    // First divide array as you need
    $listlen   = count( $toTransform );
    $partlen   = floor( $listlen / $columnsMax );
    $partrem   = $listlen % $columnsMax;
    $partition = array();
    $mark      = 0;

    for ( $px = 0; $px < $columnsMax; $px++ )
    {
        $incr             = ( $px < $partrem ) ? $partlen + 1 : $partlen;
        $partition[ $px ] = array_slice( $toTransform, $mark, $incr );
        $mark             += $incr;
    }

    // Secondly fill empty slots for easy template use
    $result = array();

    for ( $i = 0; $i < count( $partition[0] ); $i++ )
    {
        $tmp = array();

        foreach ( $partition as $column )
        {
            if ( isset( $column[ $i ] ) )
            {
                $tmp[] = $column[ $i ];
            }
            else
            {
                $tmp[] = '';
            }
        }

        $result[] = $tmp;
    }

    return $result;
}

Also I included PHPUnit test for that. You can find it at, that link.

暮凉 2024-12-17 15:29:38

array_chunk() 一直是解决方案,但如您所愿专门排序,这对你没有多大帮助。

所以这是我的五美分:

function array_chunk_vertical($input, $size_max) {
    $chunks = array();
    $chunk_count = ceil(count($input) / $size_max);

    $chunk_index = 0;
    foreach ($input as $key => $value) {
        $chunks[$chunk_index][$key] = $value;

        if (++$chunk_index == $chunk_count) {
            $chunk_index = 0;
        }
    }

    return $chunks;
}


$array = array('a', 'b', 'c', 'd', 'e', 'f');
var_dump(array_chunk_vertical($array, 2));

这会给你:

array
  0 => 
    array
      0 => string 'a' (length=1)
      3 => string 'd' (length=1)
  1 => 
    array
      1 => string 'b' (length=1)
      4 => string 'e' (length=1)
  2 => 
    array
      2 => string 'c' (length=1)
      5 => string 'f' (length=1)

这个函数的缺点是你只能告诉一个块中元素的最大数量,然后它将数组平均划分为块。因此,对于 [4] 和 max_size 3,您将得到 [2,2],与预期的 [3,1] 不同。

array_chunk() wold have been the solution but as you want it to be specially sorted, that wouldn't help you much.

So here is my five cents:

function array_chunk_vertical($input, $size_max) {
    $chunks = array();
    $chunk_count = ceil(count($input) / $size_max);

    $chunk_index = 0;
    foreach ($input as $key => $value) {
        $chunks[$chunk_index][$key] = $value;

        if (++$chunk_index == $chunk_count) {
            $chunk_index = 0;
        }
    }

    return $chunks;
}


$array = array('a', 'b', 'c', 'd', 'e', 'f');
var_dump(array_chunk_vertical($array, 2));

Which will give you:

array
  0 => 
    array
      0 => string 'a' (length=1)
      3 => string 'd' (length=1)
  1 => 
    array
      1 => string 'b' (length=1)
      4 => string 'e' (length=1)
  2 => 
    array
      2 => string 'c' (length=1)
      5 => string 'f' (length=1)

The downside of this function is that you can only tell the max number of elements in a chunk, and then it equally divides the array to chunks. So for [4] and max_size 3 you will get [2,2] unlike the expected [3,1].

维持三分热 2024-12-17 15:29:38
<?php

$five_el = array('a', 'b', 'c', 'd', 'e');

$two_el = array('a', 'b');

$three_el = array('a', 'b', 'c');

$six_el = array('a', 'b', 'c', 'd', 'e', 'f');

function multid($sorted_array) {
    $mulidarray = array();
    $row = 0;
    $column = 0;
    foreach ($sorted_array as $value) {
        if ($column == 3) {
            $row++;
        }
        $column++;
        if (!isset($mulidarray[$row])) {
            $mulidarray[$row] = array();
        }
        $multidarray[$row][] = $value;
    }

    return $multidarray;
}

var_dump(multid($five_el));
var_dump(multid($two_el));
var_dump(multid($three_el));
var_dump(multid($six_el));
<?php

$five_el = array('a', 'b', 'c', 'd', 'e');

$two_el = array('a', 'b');

$three_el = array('a', 'b', 'c');

$six_el = array('a', 'b', 'c', 'd', 'e', 'f');

function multid($sorted_array) {
    $mulidarray = array();
    $row = 0;
    $column = 0;
    foreach ($sorted_array as $value) {
        if ($column == 3) {
            $row++;
        }
        $column++;
        if (!isset($mulidarray[$row])) {
            $mulidarray[$row] = array();
        }
        $multidarray[$row][] = $value;
    }

    return $multidarray;
}

var_dump(multid($five_el));
var_dump(multid($two_el));
var_dump(multid($three_el));
var_dump(multid($six_el));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文