How to implode foreach - php

How to implode foreach() with comma?
foreach($names as $name) {
//do something
echo '' . $name .'';
}
Want to add comma after each link, except the last one.

Raveren's solution is efficient and beautiful, but here is another solution too (which can be useful in similar scenarios):
$elements = array();
foreach($names as $name) {
//do something
$elements[] = '' . $name .'';
}
echo implode(',', $elements);

You need to transform your array instead of iterating using foreach. You can do this with array_map.
PHP 5.3 syntax with closures
echo implode(", ", array_map(function($name) use($url, $title)
{
return '' . $name .'';
}, $names));
Compatible syntaxe before PHP 5.3
function createLinkFromName($name)
{
return '' . $name .'';
}
echo implode(", ", array_map('createLinkFromName', $names));
PHP 5.3 syntax with a better reability
function a_map($array, $function)
{
return array_map($function, $array);
}
echo implode(", ", a_map($names, function($name) use($url, $title)
{
return '' . $name .'';
}));

$first = TRUE;
foreach($names as $name) {
//do something
if(!$first) { echo ', '; }
$first = FALSE;
echo '', $name, '';
}

$s = '';
foreach ($names as $name) {
if ($s) $s .= ', ';
$s .= '' . $name . '';
}

foreach($names as $name) {
//do something
$str .= '' . $name .',';
}
echo substr($str,0,-1);
EDIT:
as the comments point out, this way of doing things is a little error prone if you change the separator (precisely its length) and forget the substr parameter. So use the foreach method unless performance is absolutely critical.

Here is an ugly solution using echo:
$total = (count($names) - 1 );
foreach($names as $i => $name)
{
if($i != $total)
echo '' . $name .', ';
else
echo '' . $name .'';
}

Related

PHP implode with increment value

Is there any way to add an increment value while imploding an array?
This is the piece of code I'd like to have the increment value:
$entries = '<ul class="repeatData"><li class="listEntry1">' . implode('</li><li class="listEntry'. $countme .'">', $data) . '</li></ul>';
I'd like somehow to make the variable $countme increment every time it implodes each array value, if this is even possible.
You cannot do this with implode, but look into applying an anonymous function to the array. You can probably do what you want with not much more code.
$entries = '<ul class="repeatData">';
$countme = 1;
array_walk($data, function ($element) use (&$entries, &$countme) {
$entries .= '<li class="listEntry'. $countme .'">'. $element . '</li>';
$countme++;
});
$entries .= "</ul>";
Explanation: I have written an anonymous function, told it about $entries and $counter (so it is a closure, in fact) so that it can modify them from inside its scope, and passed it to array_walk, which will apply it to all elements of the array.
There is no built in function for that. You have to write your own:
This function generalizes the problem and takes an array of glues and the data as arguments. You may refine it to fit more to your needs...
function custom_implode($glues, $pieces) {
$result = '';
while($piece = array_shift($pieces)) {
$result .= $piece;
$glue = array_shift($glues);
if(!empty($pieces)) {
$result .= $glue;
}
}
return $result;
}
Usage:
$glues = array();
for($i = 0; $i < $end; $i++) {
$glues []= '</li><li class="listEntry'. $i .'">';
}
echo custom_implode($glues, $data);
You can save the for loop which populates $glues if you customize the function a little bit more:
function custom_implode($start, $pieces) {
$result = '';
$counter = $start;
while($piece = array_shift($pieces)) {
$result .= $piece;
if(!empty($pieces)) {
$result .= '</li><li class="listEntry'. $counter .'">';
}
}
return $result;
}
To expand upon #ravloony's answer, you can use a mapping function with a counter to produce what you want, the following function could assist.
function implode_with_counter($glue, $array, $start, $pattern) {
$count = $start;
$str = "";
array_walk($array, function($value) use ($glue, $pattern, &$str, &$count) {
if (empty($str)) {
$str = $value;
} else {
$str = $str . preg_replace('/' . preg_quote($pattern, '/') . '/', $count, $glue) . $value;
$count++;
}
});
return $str;
}
Example use:
echo implode_with_counter(' ([count]) ', range(1,5), 1, '[count]');
// Output: 1 (1) 2 (2) 3 (3) 4 (4) 5
For your case:
$entries = '<ul class="repeatData"><li class="listEntry1">'
. implode_with_counter('</li><li class="listEntry[countme]">', $data, 2, '[countme]')
. '</li></ul>';
Update: Alternative
An alternative approach is to just implement a callback version of implode(), and provide a function. Which is a little more universally usable, than the pattern matching.
function implode_callback($callback, array $array) {
if (!is_callable($callback)) {
throw InvalidArgumentException("Argument 1 must be a callable function.");
}
$str = "";
$cIndex = 0;
foreach ($array as $cKey => $cValue) {
$str .= ($cIndex == 0 ? '' : $callback($cKey, $cValue, $cIndex)) . $cValue;
$cIndex++;
}
return $str;
}
Example use:
echo implode_callback(function($cKey, $cValue, $cIndex) {
return ' (' . $cIndex . ') ';
}, range(1,5));
// Output: 1 (1) 2 (2) 3 (3) 4 (4) 5
Your case:
$entries = '<ul class="repeatData"><li class="listEntry1">'
. implode_callback(function($cKey, $cValue, $cIndex) {
return '</li><li class="listEntry' . ($cIndex + 1) . '">';
}, $data)
. '</li></ul>';
No, implode doesn't work that way.
You will need to create your own function to do that.
You should also consider if this is what you really need. In both Javascript and CSS you can easily reference the n-th child of a node if you need to do that.

How to iterate this in a foreach construct

This one only covers the first record in the array -- $form[items][0][description]. How could I iterate this to be able to echo succeeding ones i.e
$form[items][1][description];
$form[items][2][description];
$form[items][3][description];
and so on and so forth?
$array = $form[items][0][description];
function get_line($array, $line) {
preg_match('/' . preg_quote($line) . ': ([^\n]+)/', $array['#value'], $match);
return $match[1];
}
$anchortext = get_line($array, 'Anchor Text');
$url = get_line($array, 'URL');
echo '' . $anchortext . '';
?>
This should do the trick
foreach ($form['items'] as $item) {
echo $item['description'] . "<br>";
}
I could help you more if I saw the body of your get_line function, but here's the gist of it
foreach ($form['items'] as $item) {
$anchor_text = get_line($item['description'], 'Anchor Text');
$url = get_line($item['description'], 'URL');
echo "{$anchor_text}";
}
You can use a for loop to iterate over this array.
for($i=0; $i< count($form['items']); $i++)
{
$anchortext = get_line($form['items'][$i]['description'], 'Anchor Text');
$url = get_line($form['items'][$i]['description'], 'URL');
echo '' . $anchortext . '';
}

How to remove "," in foreach()?

I have a code php
foreach ($cities as $city) {
echo substr($city->name . ", ", 0, -2);
}
result is: a, b, c, d, e,
How to remove "," in foreach()
Exactly: a, b, c, d, e
You could achieve the same with less code, by using the implode function.
$comma_separated = implode(',', $cities);
Should give you exactly what you want.
$str = '';
foreach ($cities as $city){
$str .= "$city, ";
}
$str = rtrim($str, " ,");
In this context you can not remove the last comma without additional tags.
You have two other options:
1. Use the standard for loop:
for ($i=0; $i < count($cities)-1; $i++) {
echo $cities[$i]->name . ", ";
}
echo $cities(count($cities)-1)->name;
2. Create a result string in the foreach, remove the last character and than print it.
Just do :-
echo implode(',', $cites);
That will give you your desired output.
I just noticed from your code that $cities is an object not an array, sorry:-
foreach($cities as $city){
$cityNames[] = $city->name;
}
echo implode(',', $cityNames);
http://www.php.net/implode
$first = true;
foreach ($cities as $city) {
if( !$first ){
echo ', ';
}else{
$first = false;
}
echo $city->name;
}
Change it a bit to something like:
$first = TRUE;
foreach ( $cities as $city )
{
if ( !$first )
{
echo( "," );
}
$first = FALSE;
echo( $city->name );
}
Use rtrim after the foreach():
$city->name = rtrim($city->name,',');
Method 1 :
$index = 0;
foreach ($cities as $city) {
$index++;
echo $city->name . ($index == count($cities)?"":",");
}
Method 2:
$str = "";
foreach ($cities as $city) {
$str .= $city->name . ",";
}
$str = substr_replace($str ,"",-1);
echo $str;

How do I grab all parameters from a URL and print it out in PHP?

How do I print out all the parameters and their value from a URL without using e.g. print $_GET['paramater-goes-here']; multiple times?
I use
print_r($_GET);
foreach($_GET as $key => $value){
echo $key . " : " . $value . "<br />\r\n";
}
The parameters are in the URL, so are available in $_GET ; and you can loop over that array using foreach :
foreach ($_GET as $name => $value) {
echo $name . ' : ' . $value . '<br />';
}
Its easy to get all request parameters from url.
<?php
print_r($_REQUEST);
?>
This will return an array format.
You can also use parse_url() and parse_str():
$url = 'http://www.example.com/index.php?a=1&b=2&c=3&d=some%20string';
$query = parse_url($url, PHP_URL_QUERY);
parse_str($query);
parse_str($query, $arr);
echo $query; // a=1&b=2&c=3&d=some%20string
echo $a; // 1
echo $b; // 2
echo $c; // 3
echo $d; // some string
foreach ($arr as $key => $val) {
echo $key . ' => ' . $val . ', '; // a => 1, b => 2, c => 3, d => 4
}
Try this.....
function get_all_get()
{
$output = "?";
$firstRun = true;
foreach($_GET as $key=>$val) {
if(!$firstRun) {
$output .= "&";
} else {
$firstRun = false;
}
$output .= $key."=".$val;
}
return $output;
}
i use:
ob_start();
var_dump($_GET);
$s=ob_get_clean();
i use:
$get = $_REQUEST;
$query_string = '?';
foreach ($get as $key => $value) {
$query_string .= $key . '=' . $value . '&';
}
$query_string;

Adding conditional formatting and punctuation to a set of variables

I often need to list items separated by comma, space or punctuation, addresses are a classic example (This is overkill for an address and is for the sake of an example!):
echo "L$level, $unit/$num $street, $suburb, $state $postcode, $country.";
//ouput: L2, 1/123 Cool St, Funky Town, ABC 2000, Australia.
As simple as it sounds, is there an easy way to "conditionally" add the custom separators between variables only if the variable exists? Is it necessary to check if each variable is set? So using the above, another address with less detail may output something like:
//L, / Cool St, , ABC , .
A slightly arduous way of checking would be to see if each variable is set and display the punctuation.
if($level){ echo "L$level, "; }
if($unit){ echo "$unit"; }
if($unit && $street){ echo "/"; }
if($street){ echo "$street, "; }
if($suburb){ echo "$suburb, "; }
//etc...
It would be good to have a function that could automatically do all the stripping/formatting etc:
somefunction("$unit/$num $street, $suburb, $state $postcode, $country.");
Another example is a simple csv list. I want to output x items separated by comma:
for($i=0; $i=<5; $i++;){ echo "$i,"; }
//output: 1,2,3,4,5,
In a loop for example, what's the best way of determining the last item of an array or the loop condition is met to not include a comma at the end of the list? One long way around this I've read of is to put a comma before an item, except the first entry something like:
$firstItem = true; //first item shouldn't have comma
for($i=0; $i=<5; $i++;){
if(!$firstItem){ echo ","; }
echo "$i";
$firstItem = false;
}
For your first example, you can use arrays in conjunction with a few of the array methods to get the desired result. For example:
echo join(', ', array_filter(array("L$level", join(' ', array_filter(array(join('/', array_filter(array($unit, $num))), $street))), $suburb, join(' ', array_filter(array($state, $postcode))), $country))) . '.';
This one-liner is quite complicated to read, so one can always wrap the array, array_filter and join calls into a separate method, and use that:
function merge($delimiter)
{
$args = func_get_args();
array_shift($args);
return join($delimiter, array_filter($args));
}
echo merge(', ', "L$level", merge(' ', merge('/', $unit, $num), $street), $suburb, merge(' ', $state, $postcode), $country) . '.';
You need the array_filter calls to remove the empty entries, otherwise the delimeters would still be printed out.
For your second example, add the items to an array, then use join to insert the delimeter:
$arr = array();
for($i=0; $i=<5; $i++)
{
$arr[] = $i;
}
echo(join(',', $arr));
While Phillip's answer addresses your question, I wanted to supplement it with the following blog post by Eric Lippert. Although his discussion is in c#, it applies to any programming language.
There's a simple solution to your second problem:
for($i=0; $i<=5; $i++)
$o .= "$i,";
echo chop($o, ',');
ok, take that! (but not too serious ^^)
<?php
function bothOrSingle($left, $infix, $right) {
return $left && $right ? $left . $infix . $right : ($left ? $left : ($right ? $right : null));
}
function leftOrNull($left, $postfix) {
return $left ? $left . $postfix : null;
}
function rightOrNull($prefix, $right) {
return $right ? $prefix . $right : null;
}
function joinargs() {
$args = func_get_args();
foreach ($args as $key => $arg)
if (!trim($arg))
unset($args[$key]);
$sep = array_shift($args);
return join($sep, $args);
}
$level = 2;
$unit = 1;
$num = 123;
$street = 'Cool St';
$suburb = 'Funky Town';
$state = 'ABC';
$postcode = 2000;
$country = 'Australia';
echo "\n" . '"' . joinargs(', ', rightOrNull('L', $level), bothOrSingle(bothOrSingle($unit, '/', $num), ' ', $street), bothOrSingle($state, ' ', $postcode), bothOrSingle($country, '', '.')) . '"';
// -> "L2, 1/123 Cool St, ABC 2000, Australia."
$level = '';
$unit = '';
$num = '';
$street = 'Cool St';
$suburb = '';
$state = 'ABC';
$postcode = '';
$country = '';
echo "\n" . '"' . joinargs(
', ',
leftOrNull(
joinargs(', ',
rightOrNull('L', $level),
bothOrSingle(bothOrSingle($unit, '/', $num), ' ', $street),
bothOrSingle($state, ' ', $postcode),
$country
),
'.'
)
) . '"';
// -> "Cool St, ABC."
$level = '';
$unit = '';
$num = '';
$street = '';
$suburb = '';
$state = '';
$postcode = '';
$country = '';
echo "\n" . '"' . joinargs(
', ',
leftOrNull(
joinargs(', ',
rightOrNull('L', $level),
bothOrSingle(bothOrSingle($unit, '/', $num), ' ', $street),
bothOrSingle($state, ' ', $postcode),
$country
),
'.'
)
) . '"';
// -> "" (even without the dot!)
?>
yes, i know - looks a bit like brainfuck.
Philip's solution is probably best when working with arrays (if you don't have to filter out empty values), but if you can't use the array functions--for instance, when dealing with query results returned from mysqli_fetch_object()--then one solution is just a simple if statement:
$list = '';
$row=mysqli_fetch_object($result);
do {
$list .= (empty($list) ? $row->col : ", {$row->col}");
} while ($row=mysqli_fetch_object($result));
Or, alternatively:
do {
if (isset($list)) {
$list .= ", {$row->col}";
} else $list = $row->col;
} while ($row=mysqli_fetch_object($result));
To build a list and filter out empty values, I would write a custom function:
function makeList() {
$args = array_filter(func_get_args()); // as per Jon Benedicto's answer
foreach ($args as $item) {
if (isset($list)) {
$list .= ", $item";
} else {
$list = $item;
}
}
if (isset($list)) {
return $list;
} else return '';
}
Then you can call it like so:
$unitnum = implode('/',array_filter(array($unit,$num)));
if ($unitnum || $street) {
$streetaddress = trim("$unitnum $street");
} else $streetaddress = '';
if ($level) {
$level = "L$level";
}
echo makeList($level, $streetaddress, $suburb, $state $postcode, $country).'.';
I always find that its both faster and easier to use the language's array methods. For instance, in PHP:
<?php
echo join(',', array('L'.$level, $unit.'/'.$num,
$street, $suburb, $state, $postcode, $country));
Just take out the last comma, i.e replace it with nothing.
$string1 = "L$level, $unit/$num $street, $suburb, $state $postcode, $country.";
$string1 = eregi_replace(", \.$", "\.", $string1);
echo $string1;
This will do the work.
<?php
$level = 'foo';
$street = 'bar';
$num = 'num';
$unit = '';
// #1: unreadable and unelegant, with arrays
$values = array();
$values[] = $level ? 'L' . $level : null;
// not very readable ...
$values[] = $unit && $num ? $unit . '/' . $num : ($unit ? $unit : ($num ? $num : null));
$values[] = $street ? $street : null;
echo join(',', $values);
// #2: or, even more unreadable and unelegant, with string concenation
echo trim(
($level ? 'L' . $level . ', ' : '') .
($unit && $num ? $unit . '/' . $num . ', ' : ($unit ? $unit . ', ' : ($num ? $num . ', ': '')) .
($street ? $street . ', ': '')), ' ,');
// #3: hey, i didn't even know that worked (roughly the same as #1):
echo join(', ', array(
$level ? 'L' . $level : null,
$unit && $num ? $unit . '/' . $num : ($unit ? $unit : ($num ? $num : null)),
$street ? $street : null
));
?>

Categories