PHP重新排序包含重复项的数组,以在重复项之间建立/保持距离
想象一下包含元素的阵列-零售、零售、娱乐、娱乐 我需要对它们进行排序,这样就不会有重复的元素彼此相邻,但总体顺序可能非常随机-零售、娱乐、零售、娱乐 我已经尝试了uasort(),但无法退出,因为它会比较所有可能的对,我想我应该存储在外部数组中,已经对检查过的元素进行排序,以了解在哪种情况下返回-或+integer,是否可以移动多个位置,即返回-2或uasort回调中的smthing 输入数组PHP重新排序包含重复项的数组,以在重复项之间建立/保持距离,php,arrays,sorting,duplicates,Php,Arrays,Sorting,Duplicates,想象一下包含元素的阵列-零售、零售、娱乐、娱乐 我需要对它们进行排序,这样就不会有重复的元素彼此相邻,但总体顺序可能非常随机-零售、娱乐、零售、娱乐 我已经尝试了uasort(),但无法退出,因为它会比较所有可能的对,我想我应该存储在外部数组中,已经对检查过的元素进行排序,以了解在哪种情况下返回-或+integer,是否可以移动多个位置,即返回-2或uasort回调中的smthing 输入数组$Input=[“零售”、“零售”、“食品”、“慈善”、“娱乐”、“娱乐”、“交通”、“化妆品”] 输出
$Input=[“零售”、“零售”、“食品”、“慈善”、“娱乐”、“娱乐”、“交通”、“化妆品”]代码>
输出数组应该像$Output=[“零售”、“食品”、“零售”、“慈善”、“娱乐”、“交通”、“娱乐”、“化妆品”]代码>
我的尝试:
我找到了一种排序方法,也许任何人都有更好的想法:
受此启发,我决定将数据压缩成一个值和计数的关联数组,然后将数组从最频繁到最不频繁排序。我循环遍历数组,只处理第一个元素。我将该值添加到输出数组中,然后减少其计数并将其移动到下一个元素之后的位置
我已经建立了一个故障保护,以防止在无法获得完美结果时出现无限循环
如果没有值多次出现,则永远不会进入循环
代码:()
产出:
Array
(
[0] => Retail
[1] => Food
[2] => Retail
[3] => 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',
)
---
我试着让排序数组靠近输入数组。
首先,我从数组中删除所有非匹配元素,然后尝试插入它们。
如果剩下任何元素,我将遍历阵列,将它们插入任何合适的位置,避免无休止的循环。结果得到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>";
$input=[“慈善”、“零售”、“零售”、“零售”、“零售”、“零售”、“零售”、“慈善”、“慈善”、“慈善”、“慈善”、“a”];
$laRest=[];
$sorted=[];
$laNoPlace=[];
而(计数($input)>0){
对于($i=0;$i0){
而(计数($laRest)>0){
$lsElement=数组移位($laRest);
对于($i=0;$i”;
打印(laNoPlace);
回声“
”;
稍后我将添加和上一次尝试……您是否确定要获得该特定的输出订单,或者是否也可以接受没有两个名称相同的项目的任何其他订单?是否需要保留尽可能多的原始顺序,或者(比如)以完全相反的顺序显示的整个输出数组也可以接受?在你的需求无法满足的情况下,比如输入是[foo,foo,bar,foo]时,你想如何处理这些事情?不,顺序可以是随机的,但如果顺序尽可能接近原始顺序(减去)重复的话会更好。我称之为“洗牌”,而不是“排序”。几乎所有排序算法都只比较两个项目的排名。这显然需要比较两个以上的项目。但是,这是一个多么有趣的问题。如果您的输入数据使所需的排序变得不可能,例如f.e.['Retail','Retail','Food','Retail']
Shuffle不应该被视为alogorithm中一种高效/有效的技术。Bravo,它在这方面做得很好:['Peter','Peter','Paul','Paul','Paul','Paul']
。这就是我要去的地方,但我认为edge cases仍然会绊倒它。我在寻找某种“排斥”算法。另一个附带案例:['Charity','Entertainment','Retail','Retail','Retail'];抱歉打扰了不,一点也不麻烦。我很感激举报。我不能暂时删除我的答案,不是因为它被接受,而是我会在晚餐/家庭时间后修复它。干杯@Fat@Fat谢谢,我添加了另一个arsort来更正逻辑
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',
)
---
$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>";