2011-10-18 31 views
6

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

Supongamos que tengo estos 2 conjuntos:

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

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

Ahora quisiera ordenar mi arsenal $data de acuerdo con el orden en mi arsenal $order.
Esto es lo que me gustaría que el resultado sea:

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

puedo lograr esto fácilmente mediante la ejecución de un bucle anidado, pero eso no sería escalar bien (mi matriz es bastante grande, y las matrices tener muchos más campos).

Respuesta

4

No hay una función incorporada para esto en PHP y no puedo pensar en ninguna función personalizada, lo que haría esto usando usort. Pero array_map es lo suficientemente simple, ¿por qué no usarlo en su lugar?

$sorted = array_map(function($v) use ($data) { 
    return $data[$v - 1]; 
}, $order); 
+0

im no puedo usar funciones anónimas con mi versión actual de php: ¿cómo funcionaría esto sin usarlas? –

+0

ha abierto una pregunta aquí http://stackoverflow.com/questions/13589707/php-modify-code-to-avoid-anonymous-functions –

0

Puede intentar usar una clasificación personalizada con usort(). De esta forma puede usar la primera matriz para determinar el orden de la segunda matriz.

+0

He mirado a la orden, pero no sé si/cómo funciona con arreglos multidimensionales. – MegaHit

+0

Eso es lo que lo hace tan útil. Usted define una función que tiene acceso a todo el elemento ya sea solo una cadena o una matriz multidimensional. Entonces, en la función de comparación puede comparar cada índice de valores en la matriz de orden. Entonces algo como esto: return (array_search ($ a ['id'], $ order)> array_search ($ b ['id'], $ order))? -1: 1; –

4

En su ejemplo los identificadores de la matriz $ datos se están numeradas consecutivamente y a partir de 1. El código Doy a continuación supone que esto 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 se puede ver que funciona para sus datos de ejemplo.

EDITAR

Si el supuesto mencionado anteriormente no se cumple, el siguiente código será conseguir 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 para la prueba.

Al invocar array_flip() en la matriz $ order se puede usar para la búsqueda de posición. Esto es como una búsqueda de hashtable, que es lineal en el tiempo, o O (n). No puedes hacer mejor.

+0

Su última solución es básicamente ejecutar un bucle anidado azucarado.No creo que eso escale bien. – MegaHit

+0

@MegaHit vea el código actualizado en mi respuesta, no puede hacer nada mejor que eso. –

0

Así sería como lo haría. Utilizaría una función de 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>"; 
Cuestiones relacionadas