2013-08-09 2 views
0

Я просматриваю функции сортировки массива PHP, чтобы найти способ сделать следующее, но не может справиться с этим.Сортировка массива по значению, оставляющему значение ключа неизменным

Пример

Array ( 
[77] => 79 
[72] => 78 
[71] => 78 
[82] => 79 
[76] => 79 
[73] => 78 
[75] => 78) 

, и я хочу вновь чтобы его

Array ( 
[72] => 78 
[71] => 78 
[73] => 78 
[75] => 78 
[77] => 79 
[82] => 79 
[76] => 79) 

уведомления путь Уважайте ключа порядок они были первоначально в них только расположены в соответствии со значением (так что 77, который был первым в 79, все еще первый в 79 и т. Д.)

Я думал, что он будет работать, но это не

asort($categories); 
foreach ($categories as $key => $val) { 
    echo "$key = $val\n"; 
    echo "<br>"; 
} 

выход (простите, пожалуйста, знак равенства)

74 = 78 
85 = 78 
75 = 78 
73 = 78 
70 = 78 
71 = 78 
72 = 78 
82 = 79 
86 = 79 
81 = 79 
77 = 79 
80 = 79 
76 = 79 
+0

разбирать() гарантирует порядок по значению и удержания ключа, но не дает никаких гарантий того, что несколько ключей с то же значение будет упорядочено любым способом –

+0

Алгоритм Quicksort не позволяет обрабатывать это, потому что элементы не обрабатываются последовательно по типу; вам может понадобиться реализовать что-то вроде сортировки пузыря или сортировки слияния вручную –

+0

есть ли определенная причина, в которой вы нуждаетесь в этом конкретном порядке? –

ответ

3

Возможно, возможно интегрировать это в некоторую реализацию вида пузыря, как предполагает Марк, но будет иметь место компромисс в скорости. Если скорость не является проблемой для начала, вот наивная реализация, которая делает то, что вы хотите.

Он просто продолжает рассчитывать на какие клавиши были использованы для конкретного значения, а затем удостоверяется окончательный отсортированные почестей массив, который заказ:

function sort_keys_intact(&$a) { 
    $b = array(); 
    $values = array(); 
    foreach ($a as $k => $v) { 
     $values[$v][] = $k; 
    } 
    asort($a); 
    $used = 0; 
    foreach ($a as $k => $v) { 
     if ($used == count($values[$v]) + 1) { 
      $used = 0; 
     } 
     $b[$values[$v][$used]] = $v; 
     $used++; 
    } 
    $a = $b; 
} 

Тестовый прогон:

echo 'Before:' . PHP_EOL; 
print_r($categories); 
sort_keys_intact($categories); 
echo 'After:' . PHP_EOL; 
print_r($categories); 

Выход

Before: 
Array 
(
    [77] => 79 
    [72] => 78 
    [71] => 78 
    [82] => 79 
    [76] => 79 
    [73] => 78 
    [75] => 78 
) 
After: 
Array 
(
    [72] => 78 
    [71] => 78 
    [73] => 78 
    [75] => 78 
    [77] => 79 
    [82] => 79 
    [76] => 79 
) 
+0

Скорость совсем не проблема здесь вообще и никогда не будет. Функция отлично работала – byronyasgur

0

Не знакомы с PHP, так не знаю, как вы могли бы сделать это в PHP (возможно, вот проблема), но вы можете создать второй список, который выглядит например:

[77] => (79,1) 
[72] => (78,2) 
[71] => (78,3) 
[82] => (79,4) 
[76] => (79,5) 
[73] => (78,6) 
[75] => (78,7) 

Это кортеж с первоначальным значением и стоимостью заказа. Сделайте сортировку, а затем удалите порядок для каждого, чтобы создать желаемый формат.

0

я сделать что-то вроде этого:

function my_sort(&$array) 
{ 
    $i = 0; 
    foreach ($array as &$val) 
    $val = [$i++, $val]; 

    uasort($array, function($a, $b) { 
    return $a[1] - $b[1] ?: $a[0] - $b[0]; 
    }); 

    foreach ($array as &$val) 
    $val = $val[1]; 
} 

который я думаю, это просто реализация @ ответ Nuclearman в.

Предполагается, что все значения являются целыми числами. Если это не так, вам нужно будет изменить $a[1] - $b[1], чтобы отобразить, как следует сортировать значения. (Если значения одинаковы, то функция сортировки возвращает $a[0] - $b[0].)

0

ответы Didnt работал для меня, поэтому я написал функцию мой один, чтобы решить эту проблему:

function sort_value_leave_key(&$arr){ 

$z = array(); 
foreach ($arr as $k => $v){ 
    $z[$v.rand(1111,9999)] = $k; 
} 
krsort($z); 

$arr = array(); 
foreach($z as $k => $v){ 
    $arr[$v] = substr($k,0,-4); 
} 

} 
Смежные вопросы