PHP: ordena una matriz multidimensional por otra matriz

3 minutos de lectura

avatar de usuario
megaéxito

Estoy tratando de ordenar una matriz multidimensional por otra matriz, pero hasta ahora me he quedado corto.
array_multisort parece estar funcionando solo para la clasificación real.

Supongamos que tengo estas 2 matrices:

$order = array(2,3,1);

$data = array(
    array('id' => 1, 'title' => 'whatever'),
    array('id' => 2, 'title' => 'whatever'),
    array('id' => 3, 'title' => 'whatever')
);

Ahora me gustaría ordenar mi $data matriz de acuerdo con el orden en mi $order formación.
Este es el resultado que me gustaría que fuera:

$data = array(
    array('id' => 2, 'title' => 'whatever'),
    array('id' => 3, 'title' => 'whatever')
    array('id' => 1, 'title' => 'whatever'),
);

Puedo lograr esto fácilmente ejecutando un bucle anidado, pero eso no escalaría bien (mi matriz es bastante grande y las matrices tienen muchos más campos).

avatar de usuario
Mridul

Así sería como lo haría. Usaría una función usort personalizada (arr_sort) junto con la matriz $data.

<?php
$order = array(2,3,1);
$data = array(
    array('id' => 1, 'title' => 'whatever'),
    array('id' => 2, 'title' => 'whatever'),
    array('id' => 3, 'title' => 'whatever')
);
function arr_sort($a,$b){
  global $order;
  foreach ($order as $key => $value) {
    if ($value==$a['id']) {
      return 0;
      break;
    }
    if ($value==$b['id']) {
      return 1;
      break;
    }
  }
}
usort($data,'arr_sort');
echo "<pre>";
print_r($data);
echo "<pre>";

  • ¡Funciona perfectamente!

    – Yatix

    31 de octubre de 2019 a las 7:13

  • No puedo usar funciones anónimas con mi versión actual de php. ¿Cómo funcionaría esto sin usarlas?

    – GWed

    27 de noviembre de 2012 a las 17:17

  • he abierto una pregunta aquí stackoverflow.com/questions/13589707/…

    – GWed

    27 de noviembre de 2012 a las 17:40

avatar de usuario
Jan Henk

En su ejemplo, los identificadores en la matriz $data están numerados consecutivamente y comienzan en 1. El código que doy a continuación asume que este es siempre el caso. Si este no es el caso, el código no funciona.

$result = array();
$index = 0;
foreach ($order as $position) {
    $result[$index] = $data[$position - 1];
    $index++;
}

En http://codepad.org/YC8w0yHh puede ver que funciona para sus datos de ejemplo.

EDITAR

Si la suposición mencionada anteriormente no se cumple, el siguiente código logrará el mismo resultado:

<?php

$data = array(
    array('id' => 1, 'title' => 'whatever'),
    array('id' => 2, 'title' => 'whatever'),
    array('id' => 3, 'title' => 'whatever')
);

$order = array(2,3,1);
$order = array_flip($order);

function cmp($a, $b)
{
    global $order;

    $posA = $order[$a['id']];
    $posB = $order[$b['id']];

    if ($posA == $posB) {
        return 0;
    }
    return ($posA < $posB) ? -1 : 1;
}

usort($data, 'cmp');

var_dump($data);

Ver http://codepad.org/Q7EcTSfs como prueba

Al llamar a array_flip() en la matriz $order, se puede usar para buscar posiciones. Esto es como una búsqueda de tabla hash, que es lineal en el tiempo u O(n). No puedes hacerlo mejor.

  • Su última solución es básicamente ejecutar un bucle anidado azucarado. No creo que escalaría bien.

    – Megaéxito

    19 de octubre de 2011 a las 0:01

  • @MegaHit ve el código actualizado en mi respuesta, no puedes hacerlo mejor que eso.

    – Jan Henk

    19 de octubre de 2011 a las 10:09

avatar de usuario
justin lucas

Podría intentar usar una ordenación personalizada con usort(). De esta manera, puede usar la primera matriz para determinar el orden de la segunda matriz.

  • Su última solución es básicamente ejecutar un bucle anidado azucarado. No creo que escalaría bien.

    – Megaéxito

    19 de octubre de 2011 a las 0:01

  • @MegaHit ve el código actualizado en mi respuesta, no puedes hacerlo mejor que eso.

    – Jan Henk

    19 de octubre de 2011 a las 10:09

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad