Как выполнить пользовательскую сортировку в массиве и сохранить ключи

#php #arrays

#php #массивы

Вопрос:

Итак, в настоящее время у меня есть это:

 array(0=>'foo', 1=>'bar', 3=>'baz', 4=>'boo', 5=>'wahoo');
  

Чего я хочу, так это:

 array(0=>'foo', 3=>'baz', 1=>'bar', 5=>'wahoo', 4=>'boo');
  

Это упрощенный пример, мой фактический массив намного больше и сложнее, поэтому его нелегко разбить на более мелкие части и собрать заново.

Я использовал uksort, чтобы попытаться это сделать, что, я думаю, является лучшим способом продвижения вперед, но, похоже, не могу получить желаемые результаты.

Редактировать:

Я думаю, что мой упрощенный пример на самом деле запутывает проблему. Вот мой фактический массив и то, что я хочу получить в итоге.

 Array
(
    [1820] => Safety
    [1821] => Security
    [1822] => Digital Life
    [1893] => Privacy and Digital Footprints
    [1823] => Connected Culture
    [1824] => Respecting Creative Work
    [1825] => Searching
    [1826] => Research and Evaluation
    [1836] => Self-Expression and Identity
)

Array
(
    [1820] => Safety
    [1821] => Security
    [1822] => Digital Life
    [1893] => Privacy and Digital Footprints
    [1823] => Connected Culture
    [1836] => Self-Expression and Identity
    [1824] => Respecting Creative Work
    [1825] => Searching
    [1826] => Research and Evaluation
)
  

Итак, у меня почти есть числовая сортировка с двумя элементами, вырванными из последовательности.

Комментарии:

1. Это числовой или ассоциативный массив?

2. @Jared — как только ключи выходят из строя, это ассоциативно (технически это всегда ассоциативно с некоторой специальной обработкой, когда php видит числа).

3. Каковы критерии сортировки? Например. Почему baz должен быть перед bar, а boo за wahoo?

4. Есть ли какая-либо логика в порядке ваших элементов? Или вы хотите вручную изменить порядок некоторых элементов на любую позицию, которую вы хотите, сохраняя при этом их ключи?

5. В этом случае я настоятельно рекомендую создать лучший вопрос, который гораздо точнее отражает то, что вы хотите сделать. Вот несколько других вариантов: во-первых, используйте то, что здесь, и сделайте функцию сравнения осведомленной о приоритетах каждого элемента. Во-вторых, измените структуру данных, включив приоритеты и сортировку по ним в функцию сравнения.

Ответ №1:

На самом деле вы ищете uasort.

Это позволит вам использовать вашу собственную функцию сортировки и сохранить ключи.

uksort сортирует на основе ключей, а не значений.

Пример:
http://codepad.viper-7.com/E8oZ2g

 function cmp($a, $b) {
    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}

// Array to be sorted
$array = array('a', 'b', 'c', 'b');

echo "<pre>";
print_r($array);
echo "</pre>";

// Sort and print the resulting array
uasort($array, 'cmp');
echo "<pre>";
print_r($array);
echo "</pre>";
  

Вывод:

 Array
(
    [0] => a
    [1] => b
    [2] => c
    [3] => b
)

Array
(
    [0] => a
    [3] => b
    [1] => b
    [2] => c
)
  

Комментарии:

1. Сохранит ли это числовые индексы?

2. В примере ключи перемещаются вместе со значениями. Это то, что делает uasort см. добавленный пример.

3. Верно (как вы видите, мне было интересно об этом). Единственное, что я бы добавил, это foreach() то, что для доступа к порядку нового массива требуется цикл: codepad.viper-7.com/kQuwis . (И я бы предпочел, чтобы ваш код тоже был в ответе, а не только на странице codepad, но 1 в любом случае.)

4. итак, если я хочу получить code array(0 => ‘foo’, 5 => ‘wahoo’, 1 =>’bar’, 3 => ‘baz’, 4 => ‘boo’); code в качестве конечного результата с использованием uasort, как мне поступить. Насколько я понимаю, code if($ a == ‘wahoo’) return -1 code должен плавно перемещаться до самого верха, но как мне остановиться в определенной точке?

5. Вы не можете «остановить» сортировку. Если у вас есть какой-то специальный алгоритм, который выполняет сортировку, вы помещаете его в качестве функции сравнения. Но это должно работать при сравнении каждого значения с каждым другим значением.

Ответ №2:

Новый ответ, основанный на обсуждении.

Используйте uksort()

Выполните переключение в функции сравнения для совпадающих и измените их.

Пример, который работает для вашего примера выше.

 function updateKey($key)
{
   switch($key)
   {
     case 1893:
       return 1822.5;

     case 1836:
       return 1823.5;

     default:
       return $key;
   }
}

function cmp($a, $b) 
{
    $a = updateKey($a);
    $b = updateKey($b);

    // you must do the compare this way for floats (instead of just subtracting) because php implemented the compare callback poorly
    if ($a == $b) 
    {
        return 0;
    }

    return ($a < $b) ? -1 : 1;
}

uksort($array, 'cmp');
  

Ответ №3:

 //randomize array preserving keys
function shuffle_assoc( $array )
{
   $keys = array_keys( $array );
   shuffle( $keys );
   return array_merge( array_flip( $keys ) , $array );
}
  

Источник: http://www.php.net/manual/en/function .shuffle.php

Обратите внимание, что это возвращает новый массив, он не изменяет входной массив.

Комментарии:

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

2. Какую формулу или функцию вы хотите использовать для перехода от исходного массива к результирующему массиву? они отсортированы в каком-либо определенном порядке или вы просто назначаете их вручную?