PHP implode with increment value - php

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.

Related

How to count/sum this values of the same word in PHP?

I am confused to count these words,
I've some data like this :
web = 1
sistem=1
web=1
sistem=1
web=1
sistem=1
sistem=0
sistem=0
web=0
sistem=0
web=0
sistem=0
web=0
web=0
I want to make result like this :
web = 3
sistem = 3
I'm using array_count_values(), but this result is not good
Array ( [web=1] => 3 [sistem=1] => 3 [sistem=0] => 4 [web=0] => 4 )
My code like this :
foreach ($g as $key => $kata) {
if (strpos($cleanAbstrak, $kata)) {
echo $kata . $ada . "<br>";
$p[] = $kata . "=" . $ada;
// print_r($p);
echo "<br><br>";
} else {
echo $kata, $tidak . "<br>";
$q[] = $kata . "=" . $tidak;
// $m = explode(" ", $q);
// print_r($q);
// echo $q . '<br>';
echo "<br><br>";
}
}
$s = array_merge($p, $q);
echo "<br><br>";
print_r($s);
echo "<br>";
$f = array_count_values($s);
// print_r($f);
echo "<br><br>";
thank you very much if you are willing to help me
RESULT THIS CODE
Another simple way is use a counter like that:
$web=0;
$sistem=0;
foreach ($g as $key => $kata) {
if (strpos($cleanAbstrak, $kata)) {
$sistem=$sistem + $ada;
} else {
$web=$web+$tidak
}
}
echo 'web='.$web.'<br> sistem='.$sistem;
First, you need to separate word and value.
Second, you need to check the value : if it's zero you let it go (can't hold it back anymore). Else you count the value ; if it's written, i suppose it can be greater than 1 ; if it's not, it should be "word", or nothing (which would greatly facilitate counting).
Something like
<?php
$tab = [
'web=1',
'sistem=1',
'web=1',
'sistem=1',
'web=1',
'sistem=1',
'sistem=0',
'sistem=0',
'web=0',
'sistem=0',
'web=0',
'sistem=0',
'web=0',
'web=0',
];
$tab_clean = [];
foreach($tab as $item) {
preg_match('/([a-z]+)=([\d]+)/', $item, $matches);
//print_r($matches);
$word = $matches[1];
$number = $matches[2];
for($i = 0; $i < $number; $i++) {
$tab_clean[] = $word;
}
}
$tab_count = array_count_values($tab_clean);
print_r($tab_count);
?>

Accessing class instances in an array

I'm working on a project, and I've come across an issue that has me stumped. The code below is a class file and a test page to make sure it's working. It's for somebody else who is programming the site, otherwise I would code the JSON output differently. Basically, the person implementing it just has to pull a bunch of data (like below) from a database, and loop through, instantiating a class object for each result, and plugging each instance into an array, and passing the array to the printJson function, which will print the JSON string. Here is what I have:
Results.php
<?php
class Result
{
public $Category = NULL;
public $Title = NULL;
public $Price = NULL;
public function __construct($category, $title, $price)
{
$this->Category = $category;
$this->Title = $title;
$this->Price = $price;
}
public static function printJson($arrayOfResults)
{
$output = '{"results": [';
foreach ($arrayOfResults as $result)
{
$output += '{"category": "' . $result->Category . '",';
$output += '"title": "' . $result->Title . '",';
$output += '"price": "' . $result->Price . '",';
$output += '},';
}
$output = substr($output, 0, -1);
$output += ']}';
return $output;
}
}
?>
getResults.php
<?php
require_once('Result.php');
$res1 = new Result('food', 'Chicken Fingers', 5.95);
$res2 = new Result('food', 'Hamburger', 5.95);
$res3 = new Result('drink', 'Coke', 1);
$res4 = new Result('drink', 'Coffee', 2);
$res5 = new Result('food', 'Cheeseburger', 6.95);
$x = $_GET['x'];
if ($x == 1)
{
$array = array($res1);
echo Result::printJson($array);
}
if ($x == 2)
{
$array = array($res1, $res2);
echo Result::printJson($array);
}
if ($x == 3)
{
$array = array($res1, $res2, $res3);
echo Result::printJson($array);
}
if ($x == 5)
{
$array = array($res1, $res2, $res3, $res4, $res5);
echo Result::printJson($array);
}
?>
The end result is if I go to getResults.php?x=5, it will return $res1 thru $res5 (again, this is just to test, I would never do something like this in production) formatted as JSON. Right now, I get '0' outputted and I cannot for the life of me figure out why. Could my foreach loop not be written properly? Please, any help you could provide would be awesome!
It's because you're using + for concatenation rather than .:
$output .= '{"category": "' . $result->Category . '",';
$output .= '"title": "' . $result->Title . '",';
$output .= '"price": "' . $result->Price . '",';
$output .= '},';
But you should really not construct the JSON yourself, as it leads to a number of errors making for invalid JSON (trailing commas etc). Use something like this instead:
public static function printJson(array $arrayOfResults)
{
$results['results'] = array_map('get_object_vars', $arrayOfResults);
return json_encode($results);
}

Create a comma-separated string from a single column of an array of objects

I'm using a foreach loop to echo out some values from my database, I need to strip the last comma from the last loop if that makes sense.
My loop is just simple, as below
foreach($results as $result){
echo $result->name.',';
}
Which echos out
result,result,result,result,
I just need to kill that pesky last comma.
Better:
$resultstr = array();
foreach ($results as $result) {
$resultstr[] = $result->name;
}
echo implode(",",$resultstr);
1. Concat to string but add | before
$s = '';
foreach ($results as $result) {
if ($s) $s .= '|';
$s .= $result->name;
}
echo $s;
2. Echo | only if not last item
$s = '';
$n = count($results);
foreach ($results as $i => $result) {
$s .= $result->name;
if (($i+1) != $n) $s .= '|';
}
echo $s;
3. Load to array and then implode
$s = array();
foreach ($results as $result) {
$s[] = $result->name;
}
echo implode('|', $s);
4. Concat to string then cut last | (or rtrim it)
$s = '';
foreach ($results as $result) {
$s .= $result->name . '|';
}
echo substr($s, 0, -1); # or # echo rtrim($s, '|');
5. Concat string using array_map()
echo implode('|', array_map(function($result) { return $result->name; }, $results));
$result_names = '';
foreach($results as $result){
$result_names .= $result->name.',';
}
echo rtrim($result_names, ',');
I've been having the same issue with this similar problem recently. I fixed it by using an increment variable $i, initializing it to 0, then having it increment inside the foreach loop. Within that loop place an if, else, with the echo statement including a comma if the $i counter is less than the sizeof() operator of your array/variable.
I don't know if this would fix your issue per se, but it helped me with mine. I realize this question is years-old, but hopefully this will help someone else. I'm fairly new to PHP so I didn't quite understand a lot of the Answers that were given before me, though they were quite insightful, particularly the implode one.
$i=0;
foreach ($results as $result) {
$i++;
if(sizeof($results) > $i) {
echo $result . ", ";
} else {
echo $result;
}
}
In modern PHP, array_column() will allow you to isolate a column of data within an array of objects.
Code: (Demo)
$results = [
(object)['name' => 'A'],
(object)['name' => 'B'],
(object)['name' => 'C']
];
echo implode(',', array_column($results, 'name'));
Output:
A,B,C
That said, since you are iterating a result set, then you may be better served by calling a CONCAT() function in your sql, so that the values are already joined in the single value result set.
If you are processing a collection in Laravel, you can pluck() and implode():
$collection->pluck('name')->implode(',')
$arraySize = count($results);
for($i=0; $i<$arraySize; $i++)
{
$comma = ($i<$arraySize) ? ", " : "";
echo $results[$i]->name.$comma;
}
Not as pretty, but also works:
$first=true;
foreach($results as $result){
if(!$first) { echo ', '; }
$first=false;
echo $result->name;
}
Another smart way is:
foreach($results as $result){
echo ($passed ? ',' : '') . $result->name;
$passed = true;
}
In this case at first loop $passed is NULL and , doesn't print.
I know this is an old thread, but this came up recently and I thought I'd share my alternate, cleaner way of dealing with it, using next().
$array = array("A thing", "A whatsit", "eighty flange oscillators");
foreach( $array as $value ){
echo $value;
$nxt = next($array);
if($nxt) echo ", "; // commas between each item in the list
else echo ". And that's it."; // no comma after the last item.
}
// outputs:
// A thing, A whatsit, eighty flange oscillators. And that's it.
play with it here
I have to do this alot because I'm always trying to feed numbers in to jplot, I find its easier to put the comma in the front of the loop like so:
foreach($arrayitem as $k){ $string = $string.",".$k;
}
and then chop off the first character (the comma) using substr, it helps if you know a guestimate of long your string will be, I'm not sure what the limit on substr max character is.
echo substr($a,1,10000000);
hope this helps.
$a[0] = 'John Doe';
$a[1] = 'Jason statham';
$a[2] = 'Thomas Anderson';
$size = count($a);
foreach($a as $key=>$name){
$result .= $name;
if($size > $key+1) $result .=', ';
}
echo $result;
<?php
$return = array(any array)
$len = count($return);
$str = '';
$i = 1;
foreach($return as $key=>$value)
{
$str .= '<a href='.$value['cat_url'].'>'.$value['cat_title'].'</a>';
if($len > $i)
{
$str .= ',';
$i = $i+1;
}
}
echo $str;
?>
<?php
$i = 1;
$count = count( $results );
foreach( $results as $result ) {
echo $result->name;
if ( $i < $count ) echo ", ";
++$i;
}
?>
This is what I normally do, add a comma before the item rather than after, while ignoring the first loop.
$i = 0;
$string = '';
foreach($array as $item){
$string .= ($i++ ? ',' : '').$item;
}
First get all the output by using output buffering. Then, trim the comma and display it. So, do it like this:
ob_start();
foreach($results as $result)
{
echo $result->name.',';
}
$output = ob_get_clean();
echo rtrim($output, ',');
The output buffering method helps if the inside loop is very big (and OP is posting here just for brevity), then using OB is easier without changing the internals of the loop.

How to implode foreach

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 .'';
}

PHP Foreach Loop and DOMNodeList

I am trying to determine the end of a foreach loop that is seeded with a collection of DOMNodeList. Currently, I am using a for loop would like to avoid having a 'magic' number there. I do know there are only going to be 8 columns, but I would like the code me generic for other applications.
Is it possible to convert this to a Foreach loop? I have tried the end() and next() functions, but they are not returning any data and I suspect that they only work on arrays and not this DOMNodeList collection.
The code is building a CSV file without the trailing ','
Current output is:
"Value 1","Value 2","Value 3","Value 4","Value 5","Value 6","Value 7","Value 8"
Here is an example of code:
$cols = $row->getElementsByTagName("td");
$printData = true;
// Throw away the header row
if ($isFirst && $printData) {
$isFirst = false;
continue;
}
for ($i = 0; $i <= 8; $i++) {
$output = iconv("UTF-8", "ASCII//IGNORE", $cols->item($i)->nodeValue);
$output2 = trim($output);
if ($i == 8) {
// Last Column
echo "\"" . $output2 . "\"" . "\n";
} else {
echo "\"" . $output2 . "\"" . ",";
}
}
You can use:
$cols->length
To retrieve the number of items in a DOMNodeList.
See http://php.net/manual/en/class.domnodelist.php
Edit:
If you change you're code to this, you don't have to worry about the trailing comma, or the length:
$output = array();
foreach ($cols as $item) {
$output = iconv("UTF-8", "ASCII//IGNORE", $item->nodeValue);
$output2 = trim($output);
$output[] = '"' . $output2 . '"';
}
$outputstring = implode(',', $output);
$cols->length
Should give you the number of items in the list
for ($i = 0; $i < $cols->length; $i++) {
// ...
if ($i == $cols->length - 1) {
// last column

Categories