Cómo implosionar una matriz con clave y valor sin foreach en PHP

111

Sin foreach , ¿cómo puedo convertir una matriz como esta?

array("item1"=>"object1", "item2"=>"object2",......."item-n"=>"object-n");

a una cuerda como esta

item1='object1', item2='object2',.... item-n='object-n'

Ya lo pensé implode(), pero no hace que la llave implosione.

Si foreach es necesario, ¿es posible no anidar el foreach?

EDITAR: he cambiado la cadena


EDIT2 / ACTUALIZAR: Esta pregunta se hizo hace bastante tiempo. En ese momento, quería escribir todo en una línea para usar operadores ternarios y anidar llamadas de función integradas a favor de foreach. ¡Esa no fue una buena práctica! Escribir código que sea legible, ya sea conciso o no, no importa mucho.

En este caso: poner foreach en una función será mucho más legible y modular que escribir una sola línea (¡aunque todas las respuestas son geniales!).

tom91136
fuente
¿Qué tan anidado sería necesario para cada uno?
Shubham
Que estas intentando ¿Por qué tienes esas limitaciones?
Madara's Ghost
esta fue mi clase de base de datos para la aplicación web que estoy construyendo, no quiero que se vea desordenada ya que ya está poblada con un montón de foreach y for-loop todos juntos
tom91136
1
Esta respuesta seleccionada es el método que solicitó, sin embargo, debe tenerse en cuenta que es críticamente más lento y que si está almacenando esta información a través de una base de datos, sería muy superior tanto a un bucle como a esto para usar json_encode. Anexo A: willem.stuursma.name/2010/11/22/…
Caso
1
posible duplicado de la forma más rápida de implosionar una matriz asociativa con claves
Félix Gagnon-Grenier

Respuestas:

187

y de otra manera:

$input = array(
    'item1'  => 'object1',
    'item2'  => 'object2',
    'item-n' => 'object-n'
);

$output = implode(', ', array_map(
    function ($v, $k) {
        if(is_array($v)){
            return $k.'[]='.implode('&'.$k.'[]=', $v);
        }else{
            return $k.'='.$v;
        }
    }, 
    $input, 
    array_keys($input)
));

o:

$output = implode(', ', array_map(
    function ($v, $k) { return sprintf("%s='%s'", $k, $v); },
    $input,
    array_keys($input)
));
robsch
fuente
6
Este método es lo que el autor estaba pidiendo, pero debe tenerse en cuenta que es críticamente más lento y que si está almacenando esta información a través de una base de datos, sería muy superior tanto a un bucle como a esto para usar json_encode. Anexo A: willem.stuursma.name/2010/11/22/…
Caso
Ninguno de los enlaces aquí parece funcionar más, todos echo "Hello, World!";¿Debería ver ejemplos de código de esas funciones?
Félix Gagnon-Grenier
Este método es muy fácil de personalizar según la propia demanda.
Kabir Hossain
Estaba usando este método para crear opciones seleccionadas y completar la opción seleccionada, y dado que ambas matrices deben tener el mismo tamaño, puede hacer algo como esto para la segunda matriz. array_fill(0, $input, 'selected-value-you want-to-check-against');Esto generará una matriz del mismo tamaño con un valor único para todas las filas.
krasenslavov
187

Podrías usar http_build_query , así:

<?php
  $a=array("item1"=>"object1", "item2"=>"object2");
  echo http_build_query($a,'',', ');
?>

Salida:

item1=object1, item2=object2 

Manifestación

Stewe
fuente
5
Nunca usé los otros parámetros de http_build_query.
Shiplu Mokaddim
16
+1 Demonios, sí, me encanta encontrar pequeñas pepitas de bondad como esta :)
Ben
8
¡Cuidado con la codificación de cadenas! Si no está creando una URL, tal vez no la quiera en su clave y valor de matriz
Matteo
8
@Matteo Usted puede envolver http_build_queryen urldecodeevitarlo.
Afterlame
3
Solución genial. Eso era todo lo que necesitaba para una salida de depuración de la matriz am assoc.
dixus
33

Pasé medidas (100000 iteraciones), ¿qué forma más rápida de pegar una matriz asociativa?

Objetivo: Obtener una línea de 1000 artículos, en este formato: "clave: valor, clave2: valor2"

Tenemos una matriz (por ejemplo):

$array = [
    'test0' => 344,
    'test1' => 235,
    'test2' => 876,
    ...
];

Prueba número uno:

Utilice http_build_query y str_replace :

str_replace('=', ':', http_build_query($array, null, ','));

Tiempo promedio para implosionar 1000 elementos: 0.00012930955084904

Prueba número dos:

Utilice array_map e implosionar :

implode(',', array_map(
        function ($v, $k) {
            return $k.':'.$v;
        },
        $array,
        array_keys($array)
    ));

Tiempo promedio para implosionar 1000 elementos: 0.0004890081976675

Prueba número tres:

Utilice array_walk e implosionar :

array_walk($array,
        function (&$v, $k) {
            $v = $k.':'.$v;
        }
    );
implode(',', $array);

Tiempo promedio para implosionar 1000 elementos: 0.0003874126245348

Prueba número cuatro:

Utilice foreach :

    $str = '';
    foreach($array as $key=>$item) {
        $str .= $key.':'.$item.',';
    }
    rtrim($str, ',');

Tiempo promedio de implosión de 1000 elementos: 0.00026632803902445

Puedo concluir que la mejor manera de pegar la matriz es usar http_build_query y str_replace

Maxim Tkach
fuente
4
$s = ''; foreach ($array as $k=>$v) { if ($s !== null) { $s .= ','; } $s .= "{$k}:{$v}"; }supera a todos los demás.
Fleshgrinder
1
Al banco http_build_query le falta urldecode para compararlo con los demás.
nickl-
Otra opción:substr(str_replace('"', '', json_encode($headers)), 1, -1);
nickl-
1
PRECAUCIÓN: Cambia sus valores si tiene espacio. El http_build_queryreemplaza con espacios más ( +carácter).
Erfun
9

Yo usaría serialize()o json_encode().

Si bien no le dará la cadena de resultado exacta que desea, sería mucho más fácil codificar / almacenar / recuperar / decodificar más adelante.

Fantasma de Madara
fuente
3

Usando array_walk

$a = array("item1"=>"object1", "item2"=>"object2","item-n"=>"object-n");
$r=array();
array_walk($a, create_function('$b, $c', 'global $r; $r[]="$c=$b";'));
echo implode(', ', $r);

IDEONE

Shiplu Mokaddim
fuente
1
Me gusta el enfoque array_walk, pero no entiendo por qué la gente sugiere usar en create_functionlugar de simplemente usar una función anónima.
Rikki
¡Compatibilidad con @Rikki!
Shiplu Mokaddim
¡Ah! ¡No me di cuenta de que era una cosa PHP4!
Rikki
@Rikki n . Es algo anterior a PHP 5.3. La función anónima apareció por primera vez en PHP 5.3
Shiplu Mokaddim
Pero se introdujo en PHP 4.0.1, por lo que es una cosa PHP4. Semántica ... Agregar una característica tan significativa como funciones anónimas en una actualización de versión menor es extraño.
Rikki
2

Cambio

-    return substr($result, (-1 * strlen($glue)));
+    return substr($result, 0, -1 * strlen($glue));

si desea resive toda la cadena sin el último $ pegamento

function key_implode(&$array, $glue) {
    $result = "";
    foreach ($array as $key => $value) {
        $result .= $key . "=" . $value . $glue;
    }
    return substr($result, (-1 * strlen($glue)));
}

Y el uso:

$str = key_implode($yourArray, ",");
Björn
fuente
Entiendo que esta es una alternativa válida a escribir un bucle foreach cada vez. UPVOTED;)
tony gil
2

Para fines de depuración. Escritura recursiva de una matriz de matrices anidadas en una cadena. Usado para cada uno. La función almacena caracteres del idioma nacional.

function q($input)
{
    $glue = ', ';
    $function = function ($v, $k) use (&$function, $glue) {
        if (is_array($v)) {
            $arr = [];
            foreach ($v as $key => $value) {
                $arr[] = $function($value, $key);
            }
            $result = "{" . implode($glue, $arr) . "}";
        } else {
            $result = sprintf("%s=\"%s\"", $k, var_export($v, true));
        }
        return $result;
    };
    return implode($glue, array_map($function, $input, array_keys($input))) . "\n";
}
Sergey Yurich
fuente
2

También puede usar array_reduce de PHP ,

$a = ['Name' => 'Last Name'];

function acc($acc,$k)use($a){ return $acc .= $k.":".$a[$k].",";}

$imploded = array_reduce(array_keys($a), "acc");
sapenov
fuente
1

Para crear mysql donde las condiciones de la matriz

$sWheres = array('item1'  => 'object1',
                 'item2'  => 'object2',
                 'item3'  => 1,
                 'item4'  => array(4,5),
                 'item5'  => array('object3','object4'));
$sWhere = '';
if(!empty($sWheres)){
    $sWhereConditions = array();
    foreach ($sWheres as $key => $value){
        if(!empty($value)){
            if(is_array($value)){
                $value = array_filter($value); // For remove blank values from array
                if(!empty($value)){
                    array_walk($value, function(&$item){ $item = sprintf("'%s'", $item); }); // For make value string type 'string'
                    $sWhereConditions[] = sprintf("%s in (%s)", $key, implode(', ', $value));
                }
            }else{
                $sWhereConditions[] = sprintf("%s='%s'", $key, $value);
            }
        }
    }
    if(!empty($sWhereConditions)){
        $sWhere .= "(".implode(' AND ', $sWhereConditions).")";
    }
}
echo $sWhere;  // (item1='object1' AND item2='object2' AND item3='1' AND item4 in ('4', '5') AND item5 in ('object3', 'object4'))
Ajay Patidar
fuente
1

También hay var_export y print_r más comúnmente conocidos para imprimir resultados de depuración, pero ambas funciones pueden tomar un argumento opcional para devolver una cadena en su lugar.

Usando el ejemplo de la pregunta como datos.

$array = ["item1"=>"object1", "item2"=>"object2","item-n"=>"object-n"];

Usando print_rpara convertir la matriz en una cadena

Esto generará una representación legible por humanos de la variable.

$string = print_r($array, true);
echo $string;

Saldrá:

Array
(
    [item1] => object1
    [item2] => object2
    [item-n] => object-n
)

Usando var_exportpara convertir la matriz en una cadena

Lo que generará una representación de cadena php de la variable.

$string = var_export($array, true);
echo $string;

Saldrá:

array (
  'item1' => 'object1',
  'item2' => 'object2',
  'item-n' => 'object-n',
)

Debido a que es un php válido, podemos evaluarlo.

eval('$array2 = ' . var_export($array, true) . ';');
var_dump($array2 === $array);

Salidas:

bool(true)
nickl-
fuente
0

Aquí hay un ejemplo simple, usando class:

$input = array(
    'element1'  => 'value1',
    'element2'  => 'value2',
    'element3' =>  'value3'
);

echo FlatData::flatArray($input,', ', '=');

class FlatData
{

    public static function flatArray(array $input = array(), $separator_elements = ', ', $separator = ': ')
    {
        $output = implode($separator_elements, array_map(
            function ($v, $k, $s) {
                return sprintf("%s{$s}%s", $k, $v);
            },
            $input,
            array_keys($input),
            array_fill(0, count($input), $separator)
        ));
      return $output;
    }

}
Iván Ferrer
fuente