首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >包含重复项的PHP重新排序数组,以便在重复项之间保持/保持距离

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

Stack Overflow用户
提问于 2020-08-25 09:29:54
回答 3查看 153关注 0票数 1

想象元素数组-零售,零售,娱乐,娱乐

我需要对它们进行排序,这样彼此之间就没有重复的元素了,但是的总体订单可以是相当随机的-零售、娱乐、零售、娱乐

我尝试过 uasort (),但无法退出查找从何处开始,因为它将比较所有可能的对,我认为我希望存储在外部数组中已经检查过的元素,以知道在哪种情况下返回-或+整数,是否可以移动多个位置,即返回-2;或在异步回调中搜索

输入阵列$input = ['Retail', 'Retail', 'Food', 'Charity', 'Entertainment', 'Entertainment', 'Transport', 'Cosmetics'];

输出数组应该类似于$output = ['Retail', 'Food', 'Retail', 'Charity', 'Entertainment', 'Transport', 'Entertainment', 'Cosmetics'];

我的尝试:

代码语言:javascript
运行
复制
<?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);

其结果是:

阵列(7 =>化妆品4 =>娱乐6 =>传输5 =>娱乐2 =>食品3 =>慈善=>零售1 =>零售)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-08-25 13:24:39

此链接的启发,我决定将数据压缩为一个值和计数的关联数组,然后将数组从大多数排序到最少。我循环遍历数组,只处理第一个元素。我将值添加到输出数组中,然后减少其计数,并将其移到下一个元素之后的位置。

我已经建立了一个故障安全,以防止无限循环时,一个完美的结果是不可能的。

如果没有超过一次的值,则不会输入该循环。

代码:(演示)

代码语言:javascript
运行
复制
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";
}

测试用例:

代码语言:javascript
运行
复制
$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']
];

产出:

代码语言:javascript
运行
复制
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',
)
---
票数 1
EN

Stack Overflow用户

发布于 2020-08-25 10:30:02

我找到了一种分类方法,也许任何人都有更好的想法:

代码语言:javascript
运行
复制
<?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);

输出:

代码语言:javascript
运行
复制
Array
(
    [0] => Retail
    [1] => Food
    [2] => Charity
    [3] => Entertainment
    [4] => Transport
    [5] => Entertainment
    [6] => Cosmetics
    [7] => Retail
)

另一个输入示例:

代码语言:javascript
运行
复制
$array  = ['Retail', 'Retail', 'Retail', 'Retail', 'Retail', 'Food', 'Charity', 'Charity', 'Charity', 'Entertainment', 'Entertainment', 'Transport', 'Cosmetics'];

输出:

代码语言:javascript
运行
复制
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'],在我的情况下,这是可信和可接受的:

代码语言:javascript
运行
复制
<?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);

产出:

代码语言:javascript
运行
复制
Array
(
    [0] => Retail
    [1] => Food
    [2] => Retail
    [3] => Retail
)
票数 0
EN

Stack Overflow用户

发布于 2020-08-26 07:12:30

我试着将排序数组保持在输入数组附近。首先,我从数组中删除任何不合适的元素,然后尝试在以后插入它们。如果留下任何元素,我将遍历数组,将它们插入任何合适的位置,避免无休止的循环。结果得到两个数组,一个排序,一个找不到合适的位置:

代码语言:javascript
运行
复制
 $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>";
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63575906

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档