How to implode array with key and value without foreach in PHP
Asked Answered
P

14

146

Without foreach, how can I turn an array like this

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

to a string like this

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

I thought about implode() already, but it doesn't implode the key with it.

If foreach it necessary, is it possible to not nest the foreach?

EDIT: I've changed the string


EDIT2/UPDATE: This question was asked quite a while ago. At that time, I wanted to write everything in one line so I would use ternary operators and nest built in function calls in favor of foreach. That was not a good practice! Write code that is readable, whether it is concise or not doesn't matter that much.

In this case: putting the foreach in a function will be much more readable and modular than writing a one-liner(Even though all the answers are great!).

Prawn answered 11/7, 2012 at 7:11 Comment(5)
How nested foreach would be necesarry?Dyson
What are you attempting? Why do you have those constraints?Lycanthrope
this was my database class for web app i'm building, i don't want it to look messy since it's already populated with a bunch of foreach and for-loop all togetherPrawn
This selected answer is method that you asked for, however it should be noted that it is critically slower and that if you are storing this information via a database it would be vastly superior to both a loop and this to just use json_encode. Exhibit A: willem.stuursma.name/2010/11/22/…Ought
possible duplicate of Fastest way to implode an associative array with keysFluster
G
213

and another way:

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

or:

$output = implode(', ', array_map(
    function ($v, $k) { return sprintf("%s='%s'", $k, $v); },
    $input,
    array_keys($input)
));
Gallia answered 11/7, 2012 at 7:12 Comment(4)
This method is what the Author was asking for, but it should be noted that it is critically slower and that if you are storing this information via a database it would be vastly superior to both a loop and this to just use json_encode. Exhibit A: willem.stuursma.name/2010/11/22/…Ought
None of the links here seem to work anymore, they all echo "Hello, World!"; Should I be seeing code examples of those functions?Fluster
This method is very easy to customize according to own demand.Counterbalance
I was using this method to build select options and populate the selected option, and since both arrays must be the same size you can do something like this for the second array. array_fill(0, $input, 'selected-value-you want-to-check-against'); This will generate same size array with single value for all the rows.Glutenous
S
252

You could use http_build_query, like this:

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

Output:

item1=object1, item2=object2 

Demo

Smallsword answered 11/7, 2012 at 7:20 Comment(8)
is it possible to make the object1 into 'object1'Prawn
Beware of the string encoding!If you are not building an URL maybe you do not want it on your array key&valueParker
@Parker You can wrap http_build_query in urldecode to avoid it.Bohs
Genius solution. That was all I needed for a debug output of am assoc array.Eugenol
Anyway to omit key itself?Beerbohm
One should be aware of how the 4th parameter handles white space.Bhili
It changes your values if have space in it. The http_build_query replaces spaces with plus (+ ) character.Smallman
Just because you can use a brick to hammer in a nail, does not mean you should. Someone may change the shape of the brick not thinking someone is using it in place of a hammer. Use the correct tools for the job, for future-proofing a solution.Gritty
G
213

and another way:

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

or:

$output = implode(', ', array_map(
    function ($v, $k) { return sprintf("%s='%s'", $k, $v); },
    $input,
    array_keys($input)
));
Gallia answered 11/7, 2012 at 7:12 Comment(4)
This method is what the Author was asking for, but it should be noted that it is critically slower and that if you are storing this information via a database it would be vastly superior to both a loop and this to just use json_encode. Exhibit A: willem.stuursma.name/2010/11/22/…Ought
None of the links here seem to work anymore, they all echo "Hello, World!"; Should I be seeing code examples of those functions?Fluster
This method is very easy to customize according to own demand.Counterbalance
I was using this method to build select options and populate the selected option, and since both arrays must be the same size you can do something like this for the second array. array_fill(0, $input, 'selected-value-you want-to-check-against'); This will generate same size array with single value for all the rows.Glutenous
F
55

I spent measurements (100000 iterations), what fastest way to glue an associative array?

Objective: To obtain a line of 1,000 items, in this format: "key:value,key2:value2"

We have array (for example):

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

Test number one:

Use http_build_query and str_replace:

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

Average time to implode 1000 elements: 0.00012930955084904

Test number two:

Use array_map and implode:

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

Average time to implode 1000 elements: 0.0004890081976675

Test number three:

Use array_walk and implode:

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

Average time to implode 1000 elements: 0.0003874126245348

Test number four:

Use foreach:

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

Average time to implode 1000 elements: 0.00026632803902445

I can conclude that the best way to glue the array - use http_build_query and str_replace

Frumpish answered 17/6, 2016 at 15:12 Comment(5)
$s = ''; foreach ($array as $k=>$v) { if ($s !== null) { $s .= ','; } $s .= "{$k}:{$v}"; } outperforms all others.Badr
The http_build_query bench is missing urldecode to be comparative to the others.Genisia
Another option: substr(str_replace('"', '', json_encode($headers)), 1, -1);Genisia
CAUTION: It changes your values if have space in it. The http_build_query replaces spaces with plus (+ ) character.Smallman
I just tested http_build_query+urldecode vs implode. Implode was 10 times faster.Snuck
M
14

I would use serialize() or json_encode().

While it won't give your the exact result string you want, it would be much easier to encode/store/retrieve/decode later on.

Manno answered 11/7, 2012 at 7:13 Comment(0)
F
4

Using 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

Farsighted answered 11/7, 2012 at 7:28 Comment(5)
I like the array_walk approach, but I don't understand why people suggest using create_function instead of just using an anonymous function?Marasco
@Marasco Compatibility!Farsighted
Ah! I didn't realise it was a PHP4 thing!Marasco
@Marasco No. Its pre PHP 5.3 thing. Anonymous function first appeared on PHP 5.3Farsighted
But it was introduced in PHP 4.0.1, so is a PHP4 thing. Semantics... Adding a feature as significant as anonymous functions in a minor version update is bizarre.Marasco
D
4

You could use PHP's array_reduce as well,

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

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

$imploded = array_reduce(array_keys($a), "acc");
Dissatisfactory answered 27/2, 2017 at 22:5 Comment(0)
A
3

Change

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

if you want to resive the entire String without the last $glue

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

And the usage:

$str = key_implode($yourArray, ",");
Apportionment answered 11/7, 2012 at 7:16 Comment(2)
why are you using a reference array in key_implode?Meatman
you should return substr($result, 0, strlen($result) - strlen($glue)), because your substr will only return the glue valueMeatman
D
3

For debugging purposes. Recursive write an array of nested arrays to a string. Used foreach. Function stores National Language characters.

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";
}
Disadvantage answered 24/11, 2015 at 10:1 Comment(0)
C
3

Here is a simple example, using 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;
    }

}
Cairistiona answered 4/5, 2018 at 15:30 Comment(0)
N
2

For create mysql where conditions from 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'))
Nonconformist answered 24/5, 2017 at 10:9 Comment(0)
W
1

Short one:

$string = implode('; ', array_map(fn($k, $v) => "$k=$v", array_keys($array), $array));
Wooer answered 22/5, 2022 at 14:26 Comment(0)
B
0

Using explode to get an array from any string is always OK, because array is an always in standard structure.

But about array to string, is there any reason to use predefined string in codes? while the string SHOULD be in any format to use!

The good point of foreach is that you can create the string AS YOU NEED IT! I'd suggest still using foreach quiet readable and clean.

$list = array('a'=>'1', 'b'=>'2', 'c'=>'3');

$sql_val = array();
foreach ($list as $key => $value) {
    $sql_val[] = "(" . $key . ", '" . $value . "') ";
}
$sql_val = implode(', ', $sql_val);

with results:

(a, '1') , (b, '2') , (c, '3') 

|

(a: '1') , (b: '2') , (c: '3') 

|

a:'1' , b:'2' , c:'3' 

etc.

Bedel answered 19/12, 2021 at 7:32 Comment(0)
T
0

I was looking for a solution to this question and I know it's been 10 years old but halfway the page, I thought: why not string replace on a json encode. It will give you easy access on how to configure the string. Also, it's a oneliner that avoids a (foreach) loop.

It would look something like this:

$wrapperAttributesString = str_replace(['{"' , '"}', '":', '","'],['' , '', '=', ' '], json_encode($wrapperAttributes));

So, bassically what happens here is:

$wrapperAttributes['class'] = 'hi__stack--overflow';
$wrapperAttributes['style'] = 'overflow: stack; ';
$wrapperAttributes['id']    = 'oneliner_array_with_keys_tostring_attributes';

//if we were to json encode this array: it would result in this:
// {"class":"hi__stack--overflow","style":"overflow: stack; ","id":"oneliner_array_with_keys_tostring_attributes"}

now the str_replace first argument takes an array with find what, the second is an array to replace that with. so it does:

find {" and replace with nothing;

find }" and replace with nothing;

find ": and replace with =;

find "," and replace with " ; to close the attribute and space to chain next

the output would be

class="hi__stack--overflow" style="overflow: stack; " id="oneliner_array_with_keys_tostring_attributes"

Now if you woud like to have comma separated instead of space separated string, just change the last replace into find "," with ','

the output would become

class="hi__stack--overflow",style="overflow: stack; ",id="oneliner_array_with_keys_tostring_attributes

Be aware, that this might be safe for html attributes (considering the values should never have a doubleqoute), but I would definitly not use it where the values can have the same combinations as the replaces have.

This is my first post, so, if you have any feedback. Feel free to let me know, also, if I by accident, did not abide by any standards, then let me know and i wil change it asap :)

Torietorii answered 18/4, 2023 at 10:1 Comment(0)
A
-1

Also if the question is outdated and the solution not requested anymore, I just found myself in the need of printing an array for debugging purposes (throwing an exception and showing the array that caused the problem).

For this reason, I anyway propose my simple solution (one line, like originally asked):

$array = ['a very' => ['complex' => 'array']];
$imploded = var_export($array, true);

This will return the exported var instead of directly printing it on the screen and the var $imploded will contain the full export.

Ansermet answered 2/9, 2022 at 16:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.