4

I am trying to generate a string from an array. Need to concatenate the array values with a small string AFTER the value. It doesn't work for the last value.

$data = array (
  1 => array (
    'symbol' => 'salad'
  ),
  2 => array (
    'symbol' => 'wine' 
  ),
  3 => array (
    'symbol' => 'beer'
  )
);

$symbols = array_column($data, 'symbol');
$string_from_array = join($symbols, 'bar');
echo($string_from_array);

// expected output: saladbar, winebar, beerbar
// output: saladbar, winebar, beer

Qirel
  • 25,449
  • 7
  • 45
  • 62

6 Answers6

3

You can achieve it a few different ways. One is actually by using implode(). If there is at least one element, we can just implode by the delimiter "bar, " and append a bar after. We do the check for count() to prevent printing bar if there are no results in the $symbols array.

$symbols = array_column($data, "symbol");
if (count($symbols)) {
    echo implode("bar, ", $symbols)."bar";
}
Qirel
  • 25,449
  • 7
  • 45
  • 62
3

You can also achieve the desired result using array_map(), as follows:

<?php
$data = [
  1 => ['symbol' => 'salad'],
  2 => ['symbol' => 'wine'], 
  3 => ['symbol' => 'beer']
];
echo join(", ", array_map(
             fn($v) => "{$v}bar",
             array_column($data, 'symbol')
         )
);

See live code

Array_map() takes every element of the array resulting from array_column() pulling out the values from $data and with an arrow function, appends the string "bar". Then the new array yielded by array_map has the values of its elements joined with ", " to form the expected output which is then displayed.

As a recent comment indicated you could eliminate array_column() and instead write code as follows:

<?php
$data = [
  1 => ['symbol' => 'salad'],
  2 => ['symbol' => 'wine'], 
  3 => ['symbol' => 'beer']
];
echo join(", ", array_map(
             fn($row) => "{$row['symbol']}bar",
             $data
         )
);

See live code

Note while this 2nd way, may appear more direct, is it? The fact is that as array_map iterates over $data, the arrow function contains code that requires dereferencing behind the scenes, namely "$row['symbol']".

slevy1
  • 3,797
  • 2
  • 27
  • 33
  • 1
    Combining `array_column()` and `array_map()` means iterating the input x2 (unnecessarily). I do not recommend this approach. – mickmackusa Jul 25 '22 at 22:30
  • Since PHP arrays are technically not arrays but pointer lists, does the internal implementation of array_column and that of array_map involve a serious performance hit? It's my understanding that any iteration since done in C would be very fast. array_column() and array_map() together enhance simplicity and legibility. – slevy1 Jul 26 '22 at 20:20
  • My point is only that accessing `'symbol'` within `array_map()` eliminates the extra call and makes the snippet [more direct](https://stackoverflow.com/a/73116053/2943403). – mickmackusa Jul 26 '22 at 20:26
1

The join() function is an alias of implode() which

Returns a string containing a string representation of all the array elements in the same order, with the glue string between each element.

So you need to add the last one by yourself

$data = array (
  1 => array (
    'symbol' => 'salad'
  ),
  2 => array (
    'symbol' => 'wine' 
  ),
  3 => array (
    'symbol' => 'beer'
  )
);

$symbols = array_column($data, 'symbol');
$string_from_array = join($symbols, 'bar');
if(strlen($string_from_array)>0)
     $string_from_array .= "bar";
echo($string_from_array);
Kurohige
  • 1,378
  • 2
  • 16
  • 24
1

You can use array_column and implode

$data = array (
  1 => array (
   'symbol' => 'salad'
  ),
  2 => array (
    'symbol' => 'wine' 
  ),
  3 => array (
   'symbol' => 'beer'
  )
 );
 $res  = implode("bar,", array_column($data, 'symbol'))."bar";

Live Demo

Rakesh Jakhar
  • 6,380
  • 2
  • 11
  • 20
0

Try this:

$symbols = array_column($data, 'symbol');
foreach ($symbols as $symbol) {
    $symbol = $symbol."bar";
    echo $symbol;
    }

btw, you can't expect implode to do what you expect, because it places "bar" between the strings, and there is no between after the last string you get from your array. ;)

HappyAnt
  • 355
  • 1
  • 9
  • You can use `implode()` just fine, just means you have to concatenate the final `bar`. See my answer and the link in it for a live demonstration. I prefer the `implode()` approach over a loop, but that's just personal preferences (and fewer lines of code) :-) – Qirel May 11 '19 at 21:47
  • I know, but I just don't like such "hard coded" solutions where I have to add some extra code for that one particular case if I can have a solution that covers all cases. ;) – HappyAnt May 11 '19 at 21:53
  • 1
    The advantage with `implode()` in addition is that it simplifies comma-separated values (as was the expected output example). With a `foreach` loop, you'd have to trim away the trailing comma afterwards. It's not "hardcoded" any more than a `foreach` would be, we have to add the `bar` in some way or another, and that is hard-coding it regardless. Either answer will do though if you're not looking for comma-separated values! – Qirel May 11 '19 at 22:02
  • Well, though I fully agree with your comment, if you look closely, you will notice that the original code won't output what was marked as "output" in the last line, because the original code's output will have neither commas nor whitespaces. So I was guessing that it's all just about the missing concatenation of "bar" at the end and not about commas. – HappyAnt May 11 '19 at 22:14
0

Another way could be using a for loop:

$res = "";
$count = count($data);
for($i = 1; $i <= $count; $i++) {
    $res .= $data[$i]["symbol"] . "bar" . ($i !== $count ? ", " : "");
}
echo $res; //saladbar, winebar, beerbar

Php demo

The fourth bird
  • 154,723
  • 16
  • 55
  • 70