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.