3 回答

TA贡献1815条经验 获得超13个赞
我决定将数据压缩为值和计数的关联数组,然后对数组从出现次数最多的到最少出现的进行排序。我循环遍历数组并仅处理第一个元素。我将值添加到输出数组,然后递减其计数并将其移动到下一个元素之后的位置。
我内置了故障保护功能,以防止在不可能获得完美结果时出现无限循环。
如果没有值出现多次,则永远不会进入循环。
代码:(演示)
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',
)
---

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>";

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
)
- 3 回答
- 0 关注
- 134 浏览
添加回答
举报