Como implodir array com chave e valor sem foreach em PHP


112

Sem foreach , como posso transformar uma matriz como esta

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

para uma corda como esta

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

Eu pensei sobre implode() , mas não implode a chave com isso.

Se foreach for necessário, é possível não aninhar o foreach?

EDIT: Eu mudei a string


EDIT2 / UPDATE: Esta pergunta foi feita há algum tempo. Naquela época, eu queria escrever tudo em uma linha para usar operadores ternários e fazer chamadas de função incorporadas a ninho em favor de foreach. Essa não foi uma boa prática! Escrever código legível, seja conciso ou não, não importa muito.

Neste caso: colocar foreach em uma função será muito mais legível e modular do que escrever uma linha (mesmo que todas as respostas sejam ótimas!).


Como foreach aninhado seria necessário?
— Shubham

O que você está tentando? Por que você tem essas restrições?
— Madara's Ghost

esta foi minha classe de banco de dados para o aplicativo da web que estou construindo, não quero que pareça bagunçada, pois já está preenchida com um monte de foreach e for-loop todos juntos
— tom91136

1
Esta resposta selecionada é o método que você pediu; no entanto, deve-se observar que é criticamente mais lento e que, se você estiver armazenando essas informações por meio de um banco de dados, seria muito superior a um loop e usar apenas json_encode. Anexo A: willem.stuursma.name/2010/11/22/…
— Caso

Respostas:


187

e outra forma:

$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)
));

ou:

$output = implode(', ', array_map(
    function ($v, $k) { return sprintf("%s='%s'", $k, $v); },
    $input,
    array_keys($input)
));

6
Este método é o que o autor estava pedindo, mas deve ser notado que é criticamente mais lento e que se você estiver armazenando essas informações por meio de um banco de dados, seria muito superior a um loop e a apenas usar json_encode. Anexo A: willem.stuursma.name/2010/11/22/…
— Caso

Nenhum dos links aqui parece funcionar mais, todos eles echo "Hello, World!";Devo ver exemplos de código dessas funções?
— Félix Gagnon-Grenier

Este método é muito fácil de personalizar de acordo com a própria demanda.
— Kabir Hossain

Eu estava usando esse método para construir opções de seleção e preencher a opção selecionada e, como os dois arrays devem ser do mesmo tamanho, você pode fazer algo assim para o segundo array. array_fill(0, $input, 'selected-value-you want-to-check-against');Isso irá gerar uma matriz de mesmo tamanho com valor único para todas as linhas.
— krasenslavov

188

Você pode usar http_build_query , assim:

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

Resultado:

item1=object1, item2=object2 

Demo


6
Nunca usei os outros parâmetros de http_build_query.
— Shiplu Mokaddim

16
+1 Inferno, sim, adoro encontrar pequenas pepitas de bondade como esta :)
— Ben,

8
Cuidado com a codificação da string! Se você não está criando um URL, talvez não o queira em sua chave e valor de array
— Matteo

8
@Matteo Você pode embrulhar http_build_queryem urldecodeevitá-lo.
— Afterlame de

3
Solução genial. Isso era tudo que eu precisava para uma saída de depuração de uma matriz assoc.
— dixus de

33

Passei medições (100.000 iterações), que maneira mais rápida de colar uma matriz associativa?

Objetivo: Obter uma linha de 1.000 itens, neste formato: "chave: valor, chave2: valor2"

Temos array (por exemplo):

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

Teste número um:

Use http_build_query e str_replace :

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

Tempo médio para implodir 1000 elementos: 0,00012930955084904

Teste número dois:

Use array_map e implode :

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

Tempo médio para implodir 1000 elementos: 0,0004890081976675

Teste número três:

Use array_walk e implode :

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

Tempo médio para implodir 1000 elementos: 0,0003874126245348

Teste número quatro:

Use foreach :

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

Tempo médio para implodir 1000 elementos: 0,00026632803902445

Posso concluir que a melhor maneira de colar o array - use http_build_query e str_replace


4
$s = ''; foreach ($array as $k=>$v) { if ($s !== null) { $s .= ','; } $s .= "{$k}:{$v}"; }supera todos os outros.
— Fleshgrinder

1
O banco http_build_query está sem urldecode para ser comparativo com os outros.
— nickl-

Outra opção:substr(str_replace('"', '', json_encode($headers)), 1, -1);
— nickl-

1
CUIDADO: Ele muda seus valores se houver espaço nele. O http_build_querysubstitui os espaços pelo +caractere mais ( ).
— Erfun

9

Eu usaria serialize()ou json_encode().

Embora não forneça a string de resultado exata que você deseja, seria muito mais fácil codificar / armazenar / recuperar / decodificar mais tarde.


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


1
Eu gosto da abordagem array_walk, mas não entendo por que as pessoas sugerem usar em create_functionvez de apenas usar uma função anônima.
— Rikki

@Rikki Compatibility!
— Shiplu Mokaddim

Ah! Não sabia que era uma coisa do PHP4!
— Rikki

@Rikki Nenhum . É uma coisa pré-PHP 5.3. A função anônima apareceu pela primeira vez no PHP 5.3
— Shiplu Mokaddim

Mas foi introduzido no PHP 4.0.1, então é uma coisa do PHP4. Semântica ... Adicionar um recurso tão significativo quanto funções anônimas em uma atualização de versão secundária é bizarro.
— Rikki

2

mudança

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

se você quiser reviver toda a corda sem a última $ glue

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

E o uso:

$str = key_implode($yourArray, ",");

eu entendo que esta é uma alternativa válida para escrever um loop foreach todas as vezes. ATUALIZADO;)
— tony gil

2

Para fins de depuração. Recursive escreve um array de arrays aninhados em uma string. Foreach usado. A função armazena caracteres do 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";
}

2

Você também pode usar array_reduce do PHP ,

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

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

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

1

Para criar mysql onde as condições do array

$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'))

1

Também há var_export e print_r mais comumente conhecidos por imprimir saída de depuração, mas ambas as funções podem receber um argumento opcional para retornar uma string.

Usando o exemplo da pergunta como dados.

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

Usando print_rpara transformar a matriz em uma string

Isso produzirá uma representação legível por humanos da variável.

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

Irá produzir:

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

Usando var_exportpara transformar a matriz em uma string

Que irá gerar uma representação de string php da variável.

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

Irá produzir:

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

Por ser um php válido, podemos avaliá-lo.

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

Saídas:

bool(true)

0

Aqui está um exemplo simples, usando classe:

$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;
    }

}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.