objects - rsort php
Ordenar una matriz por claves basadas en otra matriz? (15)
¿Qué tal esta solución?
$order = array(1,5,2,4,3,6);
$array = array(
1 => ''one'',
2 => ''two'',
3 => ''three'',
4 => ''four'',
5 => ''five'',
6 => ''six''
);
uksort($array, function($key1, $key2) use ($order) {
return (array_search($key1, $order) > array_search($key2, $order));
});
¿Es posible en PHP hacer algo como esto? ¿Cómo harías para escribir una función? Aquí hay un ejemplo. El orden es lo más importante.
$customer[''address''] = ''123 fake st'';
$customer[''name''] = ''Tim'';
$customer[''dob''] = ''12/08/1986'';
$customer[''dontSortMe''] = ''this value doesnt need to be sorted'';
Y me gustaría hacer algo como
$properOrderedArray = sortArrayByArray($customer, array(''name'', ''dob'', ''address''));
Porque al final utilizo un foreach () y no están en el orden correcto (porque añado los valores a una cadena que debe estar en el orden correcto y no sé de antemano todas las teclas de matriz / valores).
Revisé las funciones de matriz internas de PHP, pero parece que solo se puede ordenar alfabéticamente o numéricamente.
Adopté la respuesta de @ Darkwaltz4 por su brevedad y me gustaría compartir cómo adapté la solución a situaciones en las que la matriz puede contener diferentes claves para cada iteración, como por ejemplo:
Array[0] ...
[''dob''] = ''12/08/1986'';
[''some_key''] = ''some value'';
Array[1] ...
[''dob''] = ''12/08/1986'';
Array[2] ...
[''dob''] = ''12/08/1986'';
[''some_key''] = ''some other value'';
y mantuvo una "llave maestra" como esta:
$master_key = array( ''dob'' => '' '' , ''some_key'' => '' '' );
array_merge habría ejecutado la combinación en la iteración Array [1] basada en $ master_key y produjo [''some_key''] = '''', un valor vacío, para esa iteración. Por lo tanto, array_intersect_key se usó para modificar $ master_key en cada iteración como sigue:
foreach ($customer as $customer) {
$modified_key = array_intersect_key($master_key, $unordered_array);
$properOrderedArray = array_merge($modified_key, $customer);
}
Ahí tienes:
function sortArrayByArray(array $array, array $orderArray) {
$ordered = array();
foreach ($orderArray as $key) {
if (array_key_exists($key, $array)) {
$ordered[$key] = $array[$key];
unset($array[$key]);
}
}
return $ordered + $array;
}
Esta función devuelve una matriz secundaria y ordenada basada en el segundo parámetro $ keys
function array_sub_sort(array $values, array $keys){
$keys = array_flip($keys);
return array_merge(array_intersect_key($keys, $values), array_intersect_key($values, $keys));
}
Ejemplo:
$array_complete = [
''a'' => 1,
''c'' => 3,
''d'' => 4,
''e'' => 5,
''b'' => 2
];
$array_sub_sorted = array_sub_sort($array_complete, [''a'', ''b'', ''c'']);//return [''a'' => 1, ''b'' => 2, ''c'' => 3];
Otra forma para PHP> = 5.3.0:
$customer[''address''] = ''123 fake st'';
$customer[''name''] = ''Tim'';
$customer[''dob''] = ''12/08/1986'';
$customer[''dontSortMe''] = ''this value doesnt need to be sorted'';
$customerSorted = array_replace(array_flip(array(''name'', ''dob'', ''address'')), $customer);
Resultado:
Array (
[name] => Tim
[dob] => 12/08/1986
[address] => 123 fake st
[dontSortMe] => this value doesnt need to be sorted
)
Funciona bien con cadenas y teclas numéricas.
PHP tiene funciones para ayudarte con esto:
$arrayToBeSorted = array(''west'', ''east'', ''south'', ''north'');
$order = array(''north'', ''south'', ''east'', ''west'');
// sort array
usort($arrayToBeSorted, function($a, $b) use ($order){
// sort using the numeric index of the second array
$valA = array_search($a, $order);
$valB = array_search($b, $order);
// move items that don''t match to end
if ($valA === false)
return -1;
if ($valB === false)
return 0;
if ($valA > $valB)
return 1;
if ($valA < $valB)
return -1;
return 0;
});
Usort hace todo el trabajo por usted y array_search proporciona las claves. array_search () devuelve falso cuando no puede encontrar una coincidencia para que los elementos que no están en la matriz de clasificación se muevan naturalmente al final de la matriz.
Nota: uasort () ordenará la matriz sin afectar las relaciones clave => valor.
Primera sugerencia
function sortArrayByArray($array,$orderArray) {
$ordered = array();
foreach($orderArray as $key) {
if(array_key_exists($key,$array)) {
$ordered[$key] = $array[$key];
unset($array[$key]);
}
}
return $ordered + $array;
}
Segunda sugerencia
$properOrderedArray = array_merge(array_flip(array(''name'', ''dob'', ''address'')), $customer);
Quería señalar que estas dos sugerencias son increíbles. Sin embargo, son manzanas y naranjas. ¿La diferencia? Uno es amigable no asociativo y el otro amigable asociativo. Si está utilizando 2 matrices totalmente asociativas, la combinación merge / flip se fusionará y sobreescribirá la otra matriz asociativa. En mi caso, esos no son los resultados que estaba buscando. Usé un archivo settings.ini para crear mi matriz de orden de clasificación. La matriz de datos que estaba ordenando no necesitaba ser escrita por mi contraparte de ordenación asociativa. Por lo tanto, la combinación de array destruiría mi matriz de datos. Ambos son excelentes métodos, ambos deben archivarse en cualquier caja de herramientas de desarrollo. Según sus necesidades, es posible que realmente necesite ambos conceptos en sus archivos.
SI tienes una matriz en tu matriz, tendrás que adaptar la función de Eran un poco ...
function sortArrayByArray($array,$orderArray) {
$ordered = array();
foreach($orderArray as $key => $value) {
if(array_key_exists($key,$array)) {
$ordered[$key] = $array[$key];
unset($array[$key]);
}
}
return $ordered + $array;
}
Simplemente use array_merge
o array_replace
. Array_merge
funciona comenzando con la matriz que le Array_merge
(en el orden correcto) y sobrescribiendo / agregando las claves con datos de su matriz real:
$customer[''address''] = ''123 fake st'';
$customer[''name''] = ''Tim'';
$customer[''dob''] = ''12/08/1986'';
$customer[''dontSortMe''] = ''this value doesnt need to be sorted'';
$properOrderedArray = array_merge(array_flip(array(''name'', ''dob'', ''address'')), $customer);
//Or:
$properOrderedArray = array_replace(array_flip(array(''name'', ''dob'', ''address'')), $customer);
//$properOrderedArray -> array(''name'' => ''Tim'', ''address'' => ''123 fake st'', ''dob'' => ''12/08/1986'', ''dontSortMe'' => ''this value doesnt need to be sorted'')
ps - Estoy respondiendo a esta pregunta "obsoleta", porque creo que todos los bucles dados como respuestas anteriores son excesivos.
Sin magia ...
$array=array(28=>c,4=>b,5=>a);
$seq=array(5,4,28);
SortByKeyList($array,$seq) result: array(5=>a,4=>b,28=>c);
function sortByKeyList($array,$seq){
$ret=array();
if(empty($array) || empty($seq)) return false;
foreach($seq as $key){$ret[$key]=$dataset[$key];}
return $ret;
}
Tome una matriz como su orden:
$order = array(''north'', ''east'', ''south'', ''west'');
Puede ordenar otra matriz en función de los valores utilizando array_intersectDocs :
/* sort by value: */
$array = array(''south'', ''west'', ''north'');
$sorted = array_intersect($order, $array);
print_r($sorted);
O en su caso, para ordenar por claves, use los array_intersect_keyDocs :
/* sort by key: */
$array = array_flip($array);
$sorted = array_intersect_key(array_flip($order), $array);
print_r($sorted);
Ambas funciones mantendrán el orden del primer parámetro y solo devolverán los valores (o claves) de la segunda matriz.
Por lo tanto, para estos dos casos estándar no necesita escribir una función por su cuenta para realizar la clasificación / reordenación.
Un poco tarde, pero no pude encontrar la forma en que lo implementé, esta versión necesita cierre, php> = 5.3, pero podría ser modificada no para:
$customer[''address''] = ''123 fake st'';
$customer[''name''] = ''Tim'';
$customer[''dob''] = ''12/08/1986'';
$customer[''dontSortMe''] = ''this value doesnt need to be sorted'';
$order = array(''name'', ''dob'', ''address'');
$keys= array_flip($order);
uksort($customer, function($a, $b)use($keys){
return $keys[$a] - $keys[$b];
});
print_r($customer);
Por supuesto, ''dontSortMe'' debe ser resuelto, y puede aparecer primero en el ejemplo
Utilicé la solución de Darkwaltz4 pero utilicé array_fill_keys
lugar de array_flip
, para completar con NULL
si una clave no está configurada en $array
.
$properOrderedArray = array_replace(array_fill_keys($keys, null), $array);
function sortArrayByArray(array $toSort, array $sortByValuesAsKeys)
{
$commonKeysInOrder = array_intersect_key(array_flip($sortByValuesAsKeys), $toSort);
$commonKeysWithValue = array_intersect_key($toSort, $commonKeysInOrder);
$sorted = array_merge($commonKeysInOrder, $commonKeysWithValue);
return $sorted;
}
- ordenar según lo solicitado
- guardar para int-keys (debido a array_replace)
- no devolver claves no existen en inputArray
- (opcionalmente) claves de filtro que no existen en una lista de teclas dada
Código:
/**
* sort keys like in key list
* filter: remove keys are not listed in keyList
* [''c''=>''red'', ''d''=>''2016-12-29''] = sortAndFilterKeys([''d''=>''2016-12-29'', ''c''=>''red'', ''a''=>3 ]], [''c'', ''d'', ''z'']){
*
* @param array $inputArray
* @param string[]|int[] $keyList
* @param bool $removeUnknownKeys
* @return array
*/
static public function sortAndFilterKeys($inputArray, $keyList, $removeUnknownKeys=true){
$keysAsKeys = array_flip($keyList);
$result = array_replace($keysAsKeys, $inputArray); // result = sorted keys + values from input +
$result = array_intersect_key($result, $inputArray); // remove keys are not existing in inputArray
if( $removeUnknownKeys ){
$result = array_intersect_key($result, $keysAsKeys); // remove keys are not existing in keyList
}
return $result;
}