PHP Last Array Key Issue - php

I have this simple code for pasting images from a directory, I've sorted them into an array but the problem I can't seem to work out is how to get the last array to be different.
This is my code so far:
foreach($images as $image){
echo("{image : '$image'}, ");
}
I'm looking to keep print the single items in the array but on the last one I'd like to not have the comma.
Any help would be great,
Thanks!

Simple.
function doit($image) {
return "{image: '$image'}"
}
$images = array_map('doit',$images);
$images = implode(', ',$images);

echo "{image : '".implode("'}, {image : '",$images)."'}";

Try:
<?php
$buffer = array();
foreach($images as $image){
$buffer[] = "{image : '$image'}";
}
echo implode(', ', $buffer);

Try using the key and the length of the array:
$arrLength = count($images);
foreach($images as $key=>$image){
echo("{image : '$image'}");
if($key < $arrLength - 1){ echo ", "; }
}
Or use an array_map:
function make_array($n)
{
return "{image: '$n'}"
}
$map = array_map("make_array", $images);
$new_array = implode(', ', $map);

You could do this attractively with a do..while loop:
$image = current($images);
do {
echo "{image : '$image'}";
} while (($image = next($images) && (print " ,"));
Note that you have to use print not echo there, as echo does not behave as a function.
The second part of the conditional only executes if the first part passes, so " ," will only be printed if another image exists.
If there is the possibility (as in, even the vaguest possibility) that your array may contain values that aren't non-empty strings, you'll need to be more verbose:
} while (
(false !== ($image = next($images)) &&
(print " ,")
);
I'm not convinced this is very readable, however, even split over multiple lines, so if this is the case I'd go for one of the other approaches.

Either use an if statement and check if it's the last and echo accordingly, or concatenate without echoing, trim the result after it's generated, and echo.

You could do if and else statements, where if its the last image print without comma else if it isn't print with comma.

$last = array_pop(array_keys($images));
foreach($images as $key => $image) {
if ($key == $last) {
... last image ,don't output comma
}
}

Related

How to skip foreach if same value?

I have loop value with code
foreach($season as $seasons){
echo $seasons->Combined_season ;
}
and the result is 0000000011111111111111111111111222222222222222222222223333333333333333333333344444444444444444444444555555555
How to skip if there same values?
I want the result is
012345
You are looking for "unique" values:
<?php
foreach($season as $seasons){
$result[] = $seasons->Combined_season;
}
echo implode('', array_unique($result));
A somewhat awkward but more memory efficient version would be this:
<?php
foreach($season as $seasons){
$result[$seasons->Combined_season] = $seasons->Combined_season;
}
echo implode('', $result);
And the most efficient variant:
<?php
foreach($season as $seasons){
$result[$seasons->Combined_season] = null;
}
echo implode('', array_keys($result));
All approaches have the advantage that they do not require a conditional in each loop iteration which makes them far more efficient for bigger input sets.
Here an update to answer your additional question:
I mentioned more than once in my comments that the variant 2 and 3 deliver what you are looking for. That you only have to use the values internally instead of imploding them for output.
The following is exactly the third approach from above, the only difference is that I did what I told you before in the comments: use the values instead of imploding them. As far as I can see it delivers exactly what you are looking for:
<?php
foreach($season as $seasons){
$result[$seasons->Combined_season] = null;
}
$value = array_keys($result);
$printedSeasons = [];
foreach($season as $seasons){
if (!in_array($seasons->Combined_season, $printedSeasons)) {
$printedSeasons[] = $seasons->Combined_season;
echo $seasons->Combined_season;
}
}
<?php
$values = [];
foreach($season as $seasons){
if(! in_array($seasons->Combined_season, $values)) {
$values[] = $seasons->Combined_season;
echo $seasons->Combined_season ;
}
}
basically, you store any new value in an array, and before printing a value, you check if it already is in that array.
Using the "array approach" is maybe the best approach. But if your results are sorted like in your example you could use an other approach, with a current value.
$curr_val = '';
foreach($season as $seasons){
if ($seasons->Combined_season != $curr_val){
echo $seasons->Combined_season ;
$curr_val = $seasons->Combined_season ;
}
}
You can use an external variable:
$old_value = '';
foreach($season as $seasons){
$new_value = $seasons->Combined_season;
if($old_value != $new_value)
{
echo $new_value;
$old_value = $new_value;
}
}

i dont want to display comma after displaying last value

Display comma after displaying last value:
$len = count($boltpatterns);
foreach ($boltpatterns as $key => $boltpattern) {
$st1=$boltpattern['BP'];
$st2='-';
$pos=strpos($st1,$st2);
if($pos === false){
} else {
echo $st1;
if($key != $len - 1) {
echo ',';
}
}
}
You could have simply used array_column() and implode() function.
array_column() lists all your 'BP' keys into one single dimensional array.
implode() converts this single dimensional array $arr into string, separating each entry with a comma.
$arr = array_column($boltpatterns, 'BP');
echo implode(',', $arr);
Just add a new variable that will keep track of how many items you have looped through.
$len = count($boltpatterns);
$count = 1;
foreach ($boltpatterns as $key => $boltpattern) {
$st1=$boltpattern['BP'];
$st2='-';
$pos=strpos($st1,$st2);
if($pos === false){
} else {
echo $st1;
if($count != $len) {
echo ',';
}
}
++$count;
}
You can do this like this,
$valid_data = array();
foreach ($boltpatterns as $key => $boltpattern) {
if ( false !== strpos($boltpattern['BP'],'-') ){
$valid_data[] = $boltpattern['BP'];
}
}
echo implode(", ", $valid_data);
Explanation: Here we collect all the valid date we need to display to a new array. And we use PHP inbuilt function to display them.
Hope this will help you.
$arr = array_column($boltpatterns, 'BP');
echo rtrim(implode(', ', $arr), ', ');
This is an improved version of #object-manipulator's code, with rtrim removing the trailing comma.

foreach two arrays in php?

I have two arrays like this
$slike = Array('artist2-1.jpg', 'artist2-2.jpg', 'artist2-3.jpg', 'artist2-4.jpg');
$slikethumb = Array('artist2-1_thumb.jpg',
'artist2-2_thumb.jpg',
'artist2-3_thumb.jpg',
'artist2-4_thumb.jpg');
When I foreach two arrays I want to get this output on view
echo'<a href='.$slike.'><img src='.$slikethumb.'></a>';
I know how to foreach one array, but what I have to do to combine two arrays in one foreach?
If those arrays are sorted correctly and both have same number of elements:
foreach($slike as $i => $value){
echo'<a href='.$value.'><img src='.$slikethumb[$i].'></a>';
}
Edit:
Considering your related question, You might want to think about scanning your directoy using glob and a more specific pattern, something along the lines of:
$sLike = glob('{0,1,2,3,4,5,6,7,8,9}.jpg',GLOB_BRACE);
//selects all .jpg files with names ending with number.jpg, so no _thumb.jpg files
Then, with this in mind and in light of your comment. How to remove the file extensions:
$sLike = array();//the array from dir scan
$clean = array();
foreach($sLike as $file)
{
$clean[] = substr($file, 0, strpos($file, '.')*-1);//get file name
}
$format = '<img src="%1$s_thumb.jpg" />';//output format
foreach($clean as $like)
{
    printf($format, $like);
}
Or, with a more liberal pattern used for the glob call, and if you want to go with option 2 (the one with different extensions per file):
$sLike = array();//the array from dir scan
$clean = array();
foreach($sLike as $file)
{
$endOffset = strpos($file, '.')*-1;
$clean[] = array(
substr($file, 0, $endOffset),//get file name
substr($file,$endOffset)//get extension, includes the . char!
);
}
$format = '<img src="%1$s_thumb%2$s" />';//output format
foreach($clean as $like)
{
echo vsprintf($format, $like);
}
That's about it...
What I'd do is use but a single array. The base string is the same for both images:
$slike=array(
'artist2-1',
'artist2-2',
'artist2-3',
'artist2-4'
);//remove extensions
$format = '<img src="%1$s_thumb.jpg" />';//output format
foreach($slike as $like)
{
printf($format, $like);
}
That will give you what you want, without there ver being a need for 2 arrays, as you can see on this codepad.
Benefits of this approach:
only constructs 1 array, not 2
uses printf which translates internally to a fprintf(stdout, "<your format>", zval*$like); in C, which is fast.
No excess fat: there's very little repetition. You could even change the format to artist2-%s.jpg"><img src="artist2-%s_thumb.jpg" />, and only stores the numbers in the array, but that's taking it absurdly far.
Short, and concise code
Of course, there are caveats:
less readable & maintainable code
If ever you add 1 image with a different extension (png), you'll have to refactor...
The choice is yours. If different extensions is likely to happen, you could change the code above to something like:
$slike=array(
array('artist2-1','jpg'),
array('artist2-2','png'),
array('artist2-3','gif'),
array('artist2-4','jpeg'),
);//remove extensions
$format = '<img src="%1$s_thumb.%2$s" />';//output format
foreach($slike as $like)
{
echo vsprintf($format, $like);
}
As you can see on this codepad, that'll work like a charm, too
If same number of elements in both array & sorted then,
foreach($slikethumb as $key => $val) {
echo '<a href='.$slike[$key].'><img src='.$val.'></a>';
}
You can use for loop
for($i = 0; $i< count($slike); $i++)
{
$slike_val = $slike[$i];
$slikethumb_val = $slikethumb[$i];
echo'<a href='.$slike_val.'><img src='.$slikethumb_val.'></a>';
}
You will try
foreach($slike as $key=>$slike_val)
echo'<a href='.$slike_val.'><img src='.$slikethumb[$key].'></a>';
Try like this:
<?php
$slike = array('artist2-1.jpg', 'artist2-2.jpg', 'artist2-3.jpg', 'artist2-4.jpg');
$slikethumb = array('artist2-1_thumb.jpg', 'artist2-2_thumb.jpg', 'artist2-3_thumb.jpg', 'artist2-4_thumb.jpg');
foreach($slike as $key1 => $value1)
{
echo $value1."--------->".$slikethumb[$key1]."<br />";
}
?>
Thanks
foreach ($slike as $key=>$img) {
print '<a href='.$img.'><img src='.$slikethumb[$key].'></a>';
}
Or if you want one which is not based on the ordering....
foreach ($slike as $key=>$img) {
list($name, $ext)=explode('.', $img);
$thumb=$name . '_thumb.' . $ext;
if (in_array($thumb, $slikethumb)) {
print '<a href='.$img.'><img src='.$thumb.'></a>';
} else {
...?
}
}

PHP -- identifying last key in foreach to eleminate last delimeter

I've been trying to get this to work and while I have tried many methods posted on this site on other pages, I can't get any of them to work.
I need to identify the last key so that my results don't have a , at the end. This sounds like such and easy task but I just cant seem to get it to work! At this point I'm guessing I've just had a typo or something that I overlooked. Any help would be greatly appreciated.
This is what I have:
<?php
$searchString = $_GET["s"];
$prefix = 'http://link_to_my_xml_file.xml?q=';
$suffix = '&resultsPerPage=100';
$file = $prefix . $searchString . $suffix;
if(!$xml = simplexml_load_file($file))
exit('False'.$file);
foreach($xml->results->result as $item) {
echo $item->sku . ",";
}
?>
Now this works just fine, it just has a , at the end:
12345,23456,34567,45678,
For reference my xml file is laid out like: results->result->sku, but with a lot more mixed in. I'm just singling out the fields.
Consider identifying the first instead?
$first = true;
foreach($xml->results->result as $item) {
if ($first) {
$first = false;
} else {
echo ',';
}
echo $item->sku;
}
Use rtrim()
foreach($xml->results->result as $item) {
$mystr .= $item->sku . ",";
}
echo rtrim($mystr, ",")
Should output:
12345,23456,34567,45678
Demo!
If your keys are in numerical order like: 0, 1, 2, 3 etc this could be a solution:
foreach($xml->results->result as $key => $item)
{
if( $key > 0 ) echo ", ";
echo $item->sku
}
Possible solution #1:
$first = true;
foreach ($xml->results->result as $item) {
if ($first) {
$first = false;
} else {
echo ', ';
}
echo $item->sku;
}
Possible solution #2:
$items = array();
foreach ($xml->results->result as $item) {
$items[] = $item->sku;
}
echo join(', ', $items);
You can just put everything in a string and then run:
substr($yourstr, 0, -1);
on your code to remove the last character:
http://de1.php.net/manual/en/function.substr.php
Or get the total number of entries in your array and count your position

How to use a foreach loop, but do something different on the last iteration?

This is probably a simple question, but how do you iterate through an array, doing something to each one, until the last one and do something different?
I have an array of names. I want to output the list of names separated by commas.
Joe, Bob, Foobar
I don't want a comma at the end of the last name in the array, nor if there is only one value in the array (or none!).
Update: I can't use implode() because I have an array of User model objects where I get the name from each object.
$users = array();
$users[] = new User();
foreach ($users as $user) {
echo $user->name;
echo ', ';
}
How can I achieve this and still use these objects?
Update: I was worrying too much about how many lines of code I was putting in my view script, so I decided to create a view helper instead. Here's what I ended up with:
$array = array();
foreach($users as $user) {
$array[] = $user->name;
}
$names = implode(', ', $array);
Use implode:
$names = array('Joe', 'Bob', 'Foobar');
echo implode(', ', $names); # prints: Joe, Bob, Foobar
To clarify, if there is only one object in the array, the ', ' separator will not be used at all, and a string containing the single item would be returned.
EDIT: If you have an array of objects, and you wanted to do it in a way other than a for loop with tests, you could do this:
function get_name($u){ return $u->name; };
echo implode(', ', array_map('get_name', $users) ); # prints: Joe, Bob, Foobar
$array = array('joe', 'bob', 'Foobar');
$comma_separated = join(",", $array);
output: joe,bob,Foobar
Sometimes you might not want to use implode.
The trick then is to use an auxiliary variable to monitor not the last, but the first time through the loop.
vis:
$names = array('Joe', 'Bob', 'Foobar');
$first = true;
$result = '';
foreach ($names as $name)
{
if (!$first)
$result .= ', ';
else
$first = false;
$result .= $name;
}
implode(', ', $array_of_names)
psuedocode....
integer sigh=container.getsize();
sigh--;
integer gosh=0;
foreach element in container
{
if(gosh!=sigh)
dosomething();
else
doLastElementStuff();
gosh++;
}
looking at all the other answers, it seems PHP has gotten a lot more syntactic S since I last wrote anything in it :D
I come accross this a lot building SQL statements etc.
$joiner = " ";
foreach ($things as $thing) {
echo " $joiner $thing \n";
$joiner = ',';
}
FOr some reason its easier to work out the logic if you think of the ",", "AND" or "OR" as an option/attribute that goes before an item. The problem then becomes how to suppress the the "," on the first line.
I personally found the fastest way (if you're into micro optimization) is:
if(isset($names[1])) {
foreach ($names as $name) {
$result .= $name . ', ';
}
$result = substr($result, 0, -2);
} else {
$result = $names[0];
}
isset($names[1]) is the fastest (albeit not so clear) way of checking the length of an array (or string). In this case, checking for at least two elements is performed.
I actually find it easier to create my comma delimited text a little differently. It's a bit more wordy, but it's less function calls.
<?php
$nameText = '';
for ($i = 0; $i < count($nameArray); $i++) {
if ($i === 0) {
$nameText = $nameArray[$i];
} else {
$nameText .= ',' . $nameArray[$i];
}
}
It adds the comma as a prefix to every name except where it's the first element if the array. I have grown fond of using for as opposed to foreach since I have easy access to the current index and therefore adjacent elements of an array. You could use foreach like so:
<?php
$nameText = '';
$nameCounter = 0;
foreach ($nameArray as $thisName) {
if ($nameCounter === 0) {
$nameText = $thisName;
$nameCounter++;
} else {
$nameText .= ',' . $thisName;
}
}

Categories