为了账号安全,请及时绑定邮箱和手机立即绑定

PHP重新排序包含重复项目的数组以在重复项目之间保持距离

PHP重新排序包含重复项目的数组以在重复项目之间保持距离

PHP
月关宝盒 2023-11-03 10:55:34
想象一下包含元素的数组 - 零售、零售、娱乐、娱乐我需要对它们进行排序,这样就不会有重复的元素彼此相邻,但总体顺序可能相当随机-零售、娱乐、零售、娱乐我已经尝试过uasort(),但无法退出找到从哪里开始,因为它会比较所有可能的对我想我应该喜欢存储在外部数组中已经排序检查的元素以知道在哪种情况下返回 - 或 + integer,并且是可以移动多个位置,即return -2;或者 uasort 回调中的东西输入数组$input = ['Retail', 'Retail', 'Food', 'Charity', 'Entertainment', 'Entertainment', 'Transport', 'Cosmetics'];输出数组应该看起来像$output = ['Retail', 'Food', 'Retail', 'Charity', 'Entertainment', 'Transport', 'Entertainment', 'Cosmetics'];我的尝试:<?php$input  = ['Retail', 'Retail', 'Food', 'Charity', 'Entertainment', 'Entertainment', 'Transport', 'Cosmetics'];$sorted = [];uasort(    $input,    static function ($a, $b) use (&$sorted) {        $is_a_sorted = in_array($a, $sorted, true);        $is_b_sorted = in_array($b, $sorted, true);        switch (true) {            case !$is_a_sorted && !$is_b_sorted:                $sorted[] = $a;                $sorted[] = $b;                return -1;            case $is_a_sorted || $is_b_sorted:                return 1;            default:                return 0;        }    });print_r($input);结果是:Array ( [7] => 化妆品 [4] => 娱乐 [6] => 交通 [5] => 娱乐 [2] => 食品 [3] => 慈善 [0] => 零售 [1] => 零售)
查看完整描述

3 回答

?
萧十郎

TA贡献1815条经验 获得超12个赞

我决定将数据压缩为值和计数的关联数组,然后对数组从出现次数最多的到最少出现的进行排序。我循环遍历数组并仅处理第一个元素。我将值添加到输出数组,然后递减其计数并将其移动到下一个元素之后的位置。

我内置了故障保护功能,以防止在不可能获得完美结果时出现无限循环。

如果没有值出现多次,则永远不会进入循环。

代码:(演示

function valueSeparator(array $array) {

    $maxIterations = count($array);

    $counted = array_count_values($array);

    arsort($counted);

    $iteration = 0;

    $result = [];

    while (max($counted) > 1 && $iteration < $maxIterations) {

        $count = reset($counted);

        $value = key($counted);

        $result[] = $value;

        unset($counted[$value]);

        arsort($counted);

        if ($count > 1) {

            $counted = array_merge(

                array_splice($counted, 0, 1),

                [$value => $count - 1],

                $counted

            );

        }

        ++$iteration;

    }

    array_push($result, ...array_keys($counted));

    var_export($result);

}


foreach ($arrays as $array) {

    valueSeparator($array);

    echo "\n---\n";

}

测试用例:


$arrays = [

    ['Retail', 'Retail', 'Food', 'Food', 'Retail'],

    ['Retail', 'Retail', 'Food', 'Charity', 'Entertainment', 'Entertainment', 'Transport', 'Cosmetics'],

    ['Food'],

    ['Retail', 'Retail', 'Food', 'Retail'],

    ['Retail', 'Retail', 'Retail', 'Food', 'Food', 'Food', 'Charity', 'Charity', 'Charity'],

    ['Charity', 'Entertainment', 'Retail', 'Retail' ,'Retail']

];

输出:


array (

  0 => 'Retail',

  1 => 'Food',

  2 => 'Retail',

  3 => 'Food',

  4 => 'Retail',

)

---

array (

  0 => 'Retail',

  1 => 'Entertainment',

  2 => 'Food',

  3 => 'Retail',

  4 => 'Entertainment',

  5 => 'Charity',

  6 => 'Transport',

  7 => 'Cosmetics',

)

---

array (

  0 => 'Food',

)

---

array (

  0 => 'Retail',

  1 => 'Food',

  2 => 'Retail',

  3 => 'Retail',

)

---

array (

  0 => 'Retail',

  1 => 'Food',

  2 => 'Charity',

  3 => 'Retail',

  4 => 'Food',

  5 => 'Charity',

  6 => 'Retail',

  7 => 'Food',

  8 => 'Charity',

)

---

array (

  0 => 'Retail',

  1 => 'Charity',

  2 => 'Retail',

  3 => 'Entertainment',

  4 => 'Retail',

)

---


查看完整回答
反对 回复 2023-11-03
?
慕码人2483693

TA贡献1860条经验 获得超9个赞

我尝试将排序数组保持在靠近输入数组的位置。首先,我从数组中删除任何不适合的元素,然后尝试稍后插入它们。如果剩下任何元素,我会遍历数组,将它们插入到任何合适的位置,避免无限循环。结果你得到 2 个数组,一个已排序,另一个找不到合适的位置:


 $input =  ['Charity','Retail','Retail','Retail','Retail', 'Retail' ,'Retail',  'Charity',  'Charity', 'Charity','a' ];


$laRest     = [];

$sorted     = [];

$laNoPlace  = [];


while(count($input) >0) {

    for ($i = 0; $i < count($laRest); $i++) {

        if(isset($laRest[$i]) && $laRest[$i] != end($sorted)) {

            $sorted[] = $laRest[$i];

            unset($laRest[$i]);

        }

    }

    $laRest     = array_values($laRest);

    $lsElement  = array_shift($input);

    if (end($sorted) != $lsElement) {

        $sorted[] = $lsElement;

    }

    else {

        $laRest[] = $lsElement;

    }

}


if(count($laRest) >0) {

    while(count($laRest) >0) {

        $lsElement = array_shift($laRest);

        for ($i = 0; $i < count($sorted); $i++) {

            if($i != 0 && $sorted[$i] != $lsElement && !isset($sorted[$i+1]) && $lsElement !='') {//end

                array_push($sorted, $lsElement);

                $lsElement = '';

            }

            if($i != 0 && $sorted[$i] != $lsElement && isset($sorted[$i+1]) && $sorted[$i+1] != $lsElement && $lsElement !='') {

                $lsStart = array_slice($sorted, 0, $i+1);

                $lsEnd   = array_slice($sorted , $i+1);

                $sorted  = array_merge($lsStart,  array($lsElement), $lsEnd);

                $lsElement = '';

            } 

            if($i == 0 && $sorted[$i] != $lsElement && $lsElement !='') {//start

              array_unshift($sorted, $lsElement);

              $lsElement = '';

            } 

        }

        if($lsElement != '') {

            $laNoPlace[] = $lsElement;

        }

    }

}


print_r($sorted);

echo "<HR>";

print_r($laNoPlace);

echo "<HR>";


查看完整回答
反对 回复 2023-11-03
?
繁星coding

TA贡献1797条经验 获得超4个赞

我找到了一种排序方法,也许有人有更好的想法:


<?php


$array  = ['Retail', 'Retail', 'Food', 'Charity', 'Entertainment', 'Entertainment', 'Transport', 'Cosmetics'];

$sorted = [];


while (!empty($array)) {

    $current = current($array);


    if (end($sorted) !== $current) {

        $sorted[] = $current;

        array_splice($array, key($array), 1);

    }


    $next = next($array);


    if (!$next) {

        reset($array);

        shuffle($array);

    }

}


print_r($sorted);

输出:


Array

(

    [0] => Retail

    [1] => Food

    [2] => Charity

    [3] => Entertainment

    [4] => Transport

    [5] => Entertainment

    [6] => Cosmetics

    [7] => Retail

)

另一个输入示例:


$array  = ['Retail', 'Retail', 'Retail', 'Retail', 'Retail', 'Food', 'Charity', 'Charity', 'Charity', 'Entertainment', 'Entertainment', 'Transport', 'Cosmetics'];

输出:


Array

(

    [0] => Retail

    [1] => Food

    [2] => Retail

    [3] => Charity

    [4] => Retail

    [5] => Charity

    [6] => Retail

    [7] => Charity

    [8] => Entertainment

    [9] => Transport

    [10] => Entertainment

    [11] => Cosmetics

    [12] => Retail

)

针对特殊场合的更新代码,例如当输入是这样的时,['Retail', 'Retail', 'Food', 'Retail']在我的情况下是合理且可接受的:


<?php


$array  = ['Retail', 'Retail', 'Food', 'Retail'];

$sorted = [];


$tries = 0;

$maxTries = count($array);


while (!empty($array) && $tries <= $maxTries) {

    $current = current($array);


    if (end($sorted) !== $current) {

        $sorted[] = $current;

        array_splice($array, key($array), 1);

    }


    $next = next($array);


    if (!$next) {

        reset($array);

        shuffle($array);

        $tries++;

    }

}


if (!empty($array)) {

    array_push($sorted, ...$array);

}


print_r($sorted);

输出:


Array

(

    [0] => Retail

    [1] => Food

    [2] => Retail

    [3] => Retail

)


查看完整回答
反对 回复 2023-11-03
  • 3 回答
  • 0 关注
  • 81 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信