Related
I'm currently using this:
foreach($hash_list as $key => $val){
if(in_array($search_this,$hash_list[$key])){
echo 'Found value in key '.$key;
break;
}
}
To find $search_this in this:
$hash_list = array();
$hash_list["a"] = array("dfv8p","hi8o7","d2l9f","qhx13","c7duz");
$hash_list["b"] = array("pdsyt","jjivh","nj12b","19tm2","ltsqp");
$hash_list["c"] = array("67s6q","tlwu7","c9p77","7airj","j7tej");
Is there a better way to find the key for this situation? $hash_list has about 500 arrays with 5 elements each inside.
Deadpool: #Sergey No php built-in function that I'm missing?
I dont think so. But I think it's may be little faster, but I'm not sure
$hash_list = array();
$hash_list["a"] = "dfv8p, hi8o7, d2l9f, qhx13, c7duz";
$hash_list["b"] = "pdsyt, jjivh, nj12b, 19tm2, ltsqp";
$hash_list["c"] = "67s6q, tlwu7, c9p77, 7airj, j7tej";
foreach($hash_list as $key => $val){
if(strpos($hash_list[$key], $search_this) !== false) {
echo 'Found value in key '.$key;
break;
}
}
You can use user build functions like this
function isValueExist($hash_list,$needle){
foreach($hash_list as $val){
if(in_array($needle,array_values($val))) return 1;
}
}
Usage :-
if (isValueExist($hash_list,"d2l9f")){
//DO you things here
}
You can make use of list() too ;)
<?php
$hash_list = array();
$hash_list["a"] = array("dfv8p","hi8o7","d2l9f","qhx13","c7duz");
$hash_list["b"] = array("pdsyt","jjivh","nj12b","19tm2","ltsqp");
$hash_list["c"] = array("67s6q","tlwu7","c9p77","7airj","j7tej");
$searchParam = "67s6q";
while(list($a,$b) = each($hash_list))
{
if(in_array($searchParam,$b))
{
echo "$searchParam found in $a\n";
}
}
OUTPUT :
67s6q found in c
here am trying to add a comma in the values got by the foreach loop. now the values are coming all together, but i want it to get echoed as comma separated. please suggest me what i gotta do . I know, i gotta use implode, but i don't know how to do it exactly in a loop.
foreach($_POST['insert'] as $interested) {
if(!preg_match('/^[-A-Z0-9\., ]+$/iD', $interested)) continue;
echo $interested;
}
If you want to leave your code relatively untouched (though I fixed your confusing indentation)...
$interestedValues = array();
foreach($_POST['insert'] as $interested) {
if(!preg_match('/^[-A-Z0-9\., ]+$/iD', $interested)) continue;
$interestedValues[] = $interested;
}
echo implode(',', $interestedValues);
...Or as one liners seem fashionable...
echo implode(',', preg_grep('/^[-A-Z\d., ]+$/iD', $_POST['insert']));
This can even be done as a one-liner:
echo join(', ', array_filter($_POST['insert'],
function ($str) { return preg_match('/^[-A-Z0-9\., ]+$/iD', $str); }));
Just use as its syntax is
$array=array();
foreach($_POST['insert'] as $interested) {
if(!preg_match('/^[-A-Z0-9\., ]+$/iD', $interested)) continue;
$array[]=$interested;
}
echo implode(',',$array);
If you are interested only in specific values from $_POST['insert'], then create a new array and implode that:
$justSomeValues = array();
foreach($_POST['insert'] as $interested) {
if(!preg_match('/^[-A-Z0-9\., ]+$/iD', $interested)) continue;
$justSomeValues[] = $interested;
}
echo implode(', ', $justSomeValues);
else, to implode the whole $_POST['insert'] do this:
echo implode(', ', $_POST['insert']);
put all the values in an array and use JOIN to echo csv value:
$newarray = array();
foreach($_POST['insert'] as $interested) {
if(!preg_match('/^[-A-Z0-9\., ]+$/iD', $interested)) continue;
$newarray[] = $interested;
}
echo JOIN(",",$newarray);
Since $interested clearly is a string, I assume you want to concatenate all these with ,.
$counter = 0;
foreach($_POST['insert'] as $interested) {
if(!preg_match('/^[-A-Z0-9\., ]+$/iD', $interested))
continue;
if($counter++)
echo ", ";
echo $interested;
}
This is a bit more performant than storing the values in a new array, however, you lose a bit of flexibility.
I have the following php loop that takes an array that contains a set of arrays. I use this code to convert each array to a list, so I can manipulate the elements better.
This is my code...
while ($i<sizeof($my_array)){
while(list($key,$val) = each($my_array[$i])){
$j = $i+1;
if ($key == "fruit"){
$val = "ananas".$j;
echo $val;
}
}
$i++;
}
When I print the "search" array (print_r($my_array)), the values don't change. I don't understand why this doesn't work as I had expected. Is there a solution to modify the $val without changing the loop structure and logic?
Use foreach with reference:
$i = 0;
foreach ( $my_array as $key => &$val ) {
++$i;
if ($key == "fruit"){
$val = "ananas" . $i;
echo $val;
}
}
$val is a copy of the data contained in $my_array[$i], not the actual data. To change the data in the array:
while ($i<sizeof($my_array)){
while(list($key,$val) = each($my_array[$i])){
$j = $i+1;
if ($key == "fruit"){
$my_array[$i][$key] = "ananas";
echo $my_array[$i][$key];
}
}
$i++;
}
And it's probably easier to use a foreach loop
each() doesn't pass the data as references, without modifying the loop that much:
if ($key == "fruit"){
$val = "ananas";
echo $val;
$my_array[$i][$key] = $val;
}
Of course, there are better ways to do that. But you wanted an answer that didn't change the loop structure.
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;
}
}
I am writing a SQL query creator using some parameters. In Java, it's very easy to detect the last element of an array from inside the for loop by just checking the current array position with the array length.
for(int i=0; i< arr.length;i++){
boolean isLastElem = i== (arr.length -1) ? true : false;
}
In PHP they have non-integer indexes to access arrays. So you must iterate over an array using a foreach loop. This becomes problematic when you need to take some decision (in my case to append or/and parameter while building query).
I am sure there must be some standard way of doing this.
How do you solve this in PHP?
It sounds like you want something like this:
$numItems = count($arr);
$i = 0;
foreach($arr as $key=>$value) {
if(++$i === $numItems) {
echo "last index!";
}
}
That being said, you don't -have- to iterate over an "array" using foreach in php.
You could get the value of the last key of the array using end(array_keys($array)) and compare it to the current key:
$last_key = end(array_keys($array));
foreach ($array as $key => $value) {
if ($key == $last_key) {
// last element
} else {
// not last element
}
}
Note: This doesn't work because calling next() advances the array pointer, so you're skipping every other element in the loop
why so complicated?
foreach($input as $key => $value) {
$ret .= "$value";
if (next($input)==true) $ret .= ",";
}
This will add a , behind every value except the last one!
When toEnd reaches 0 it means it is at the last iteration of the loop.
$toEnd = count($arr);
foreach($arr as $key=>$value) {
if (0 === --$toEnd) {
echo "last index! $value";
}
}
The last value is still available after the loop, so if you just want to use it for more stuff after the loop this is better:
foreach($arr as $key=>$value) {
//something
}
echo "last index! $key => $value";
If you do not want to treat the last value as special inside loops. This should be faster if you have large arrays. (If you reuse the array after the loop inside the same scope you have to "copy" the array first).
//If you use this in a large global code without namespaces or functions then you can copy the array like this:
//$array = $originalArrayName; //uncomment to copy an array you may use after this loop
//end($array); $lastKey = key($array); //uncomment if you use the keys
$lastValue = array_pop($array);
//do something special with the last value here before you process all the others?
echo "Last is $lastValue", "\n";
foreach ($array as $key => $value) {
//do something with all values before the last value
echo "All except last value: $value", "\n";
}
//do something special with the last value here after you process all the others?
echo "Last is $lastValue", "\n";
And to answer your original question "in my case to append or/and parameter while building query"; this will loop over all the values, then join them together to a string with " and " between them but not before the first value or after the last value:
$params = [];
foreach ($array as $value) {
$params[] = doSomething($value);
}
$parameters = implode(" and ", $params);
There are already many answers, but it's worth to look into iterators as well, especially as it has been asked for a standard way:
$arr = range(1, 3);
$it = new CachingIterator(new ArrayIterator($arr));
foreach($it as $key => $value)
{
if (!$it->hasNext()) echo 'Last:';
echo $value, "\n";
}
You might find something that does work more flexible for other cases, too.
One way could be to detect if the iterator has next. If there is no next attached to the iterator it means you are in the last loop.
foreach ($some_array as $element) {
if(!next($some_array)) {
// This is the last $element
}
}
SINCE PHP 7.3 :
You could get the value of the last key of the array using array_key_last($array) and compare it to the current key:
$last_key = array_key_last($array);
foreach ($array as $key => $value) {
if ($key == $last_key) {
// last element
} else {
// not last element
}
}
to get first and last element from foreach array
foreach($array as $value) {
if ($value === reset($array)) {
echo 'FIRST ELEMENT!';
}
if ($value === end($array)) {
echo 'LAST ITEM!';
}
}
So, if your array has unique array values, then determining last iteration is trivial:
foreach($array as $element) {
if ($element === end($array))
echo 'LAST ELEMENT!';
}
As you see, this works if last element is appearing just once in array, otherwise you get a false alarm. In it is not, you have to compare the keys (which are unique for sure).
foreach($array as $key => $element) {
end($array);
if ($key === key($array))
echo 'LAST ELEMENT!';
}
Also note the strict coparision operator, which is quite important in this case.
Don't add a comma after the last value:
The array:
$data = ['lorem', 'ipsum', 'dolor', 'sit', 'amet'];
The function:
$result = "";
foreach($data as $value) {
$resut .= (next($data)) ? "$value, " : $value;
}
The result:
print $result;
lorem, ipsum, dolor, sit, amet
You can still use that method with associative arrays:
$keys = array_keys($array);
for ($i = 0, $l = count($array); $i < $l; ++$i) {
$key = $array[$i];
$value = $array[$key];
$isLastItem = ($i == ($l - 1));
// do stuff
}
// or this way...
$i = 0;
$l = count($array);
foreach ($array as $key => $value) {
$isLastItem = ($i == ($l - 1));
// do stuff
++$i;
}
Assuming you have the array stored in a variable...
foreach($array as $key=>$value)
{
echo $value;
if($key != count($array)-1) { echo ", "; }
}
If you need to do something for every element except either the first or the last and only if there is more than one element in the array, I prefer the following solution.
I know there are many solutions above and posted months/one year before mine, but this is something I feel is fairly elegant in its own right. The check every loop is also a boolean check as opposed to a numeric "i=(count-1)" check, which may allow for less overhead.
The structure of the loop may feel awkward, but you can compare it to the ordering of thead (beginning), tfoot (end), tbody (current) in HTML table tags.
$first = true;
foreach($array as $key => $value) {
if ($first) {
$first = false;
// Do what you want to do before the first element
echo "List of key, value pairs:\n";
} else {
// Do what you want to do at the end of every element
// except the last, assuming the list has more than one element
echo "\n";
}
// Do what you want to do for the current element
echo $key . ' => ' . $value;
}
For instance, in web development terms, if you want to add a border-bottom to every element except the last in an unordered list (ul), then you can instead add a border-top to every element except the first (the CSS :first-child, supported by IE7+ and Firefox/Webkit supports this logic, whereas :last-child is not supported by IE7).
You can feel free to reuse the $first variable for each and every nested loop as well and things will work just fine since every loop makes $first false during the first process of the first iteration (so breaks/exceptions won't cause issues).
$first = true;
foreach($array as $key => $subArray) {
if ($first) {
$string = "List of key => value array pairs:\n";
$first = false;
} else {
echo "\n";
}
$string .= $key . '=>(';
$first = true;
foreach($subArray as $key => $value) {
if ($first) {
$first = false;
} else {
$string .= ', ';
}
$string .= $key . '=>' . $value;
}
$string .= ')';
}
echo $string;
Example output:
List of key => value array pairs:
key1=>(v1_key1=>v1_val1, v1_key2=>v1_val2)
key2=>(v2_key1=>v2_val1, v2_key2=>v2_val2, v2_key3=>v2_val3)
key3=>(v3_key1=>v3_val1)
This should be the easy way to find the last element:
foreach ( $array as $key => $a ) {
if ( end( array_keys( $array ) ) == $key ) {
echo "Last element";
} else {
echo "Just another element";
}
}
Reference : Link
I have a strong feeling that at the root of this "XY problem" the OP wanted just implode() function.
As your intention of finding the EOF array is just for the glue. Get introduced to the below tactic. You need not require the EOF:
$given_array = array('column1'=>'value1',
'column2'=>'value2',
'column3'=>'value3');
$glue = '';
foreach($given_array as $column_name=>$value){
$where .= " $glue $column_name = $value"; //appending the glue
$glue = 'AND';
}
echo $where;
o/p:
column1 = value1 AND column2 = value2 AND column3 = value3
How about using "end"?
http://php.net/manual/en/function.end.php
It sounds like you want something like this:
$array = array(
'First',
'Second',
'Third',
'Last'
);
foreach($array as $key => $value)
{
if(end($array) === $value)
{
echo "last index!" . $value;
}
}
$array = array("dog", "rabbit", "horse", "rat", "cat");
foreach($array as $index => $animal) {
if ($index === array_key_first($array))
echo $animal; // output: dog
if ($index === array_key_last($array))
echo $animal; // output: cat
}
you can do a count().
for ($i=0;$i<count(arr);$i++){
$i == count(arr)-1 ? true : false;
}
or if you're looking for ONLY the last element, you can use end().
end(arr);
returns only the last element.
and, as it turns out, you CAN index php arrays by integers. It's perfectly happy with
arr[1];
You could also do something like this:
end( $elements );
$endKey = key($elements);
foreach ($elements as $key => $value)
{
if ($key == $endKey) // -- this is the last item
{
// do something
}
// more code
}
I kinda like the following as I feel it is fairly neat. Let's assume we're creating a string with separators between all the elements: e.g. a,b,c
$first = true;
foreach ( $items as $item ) {
$str = ($first)?$first=false:", ".$item;
}
Here's my solution:
Simply get the count of your array, minus 1 (since they start in 0).
$lastkey = count($array) - 1;
foreach($array as $k=>$a){
if($k==$lastkey){
/*do something*/
}
}
foreach ($array as $key => $value) {
$class = ( $key !== count( $array ) -1 ) ? " class='not-last'" : " class='last'";
echo "<div{$class}>";
echo "$value['the_title']";
echo "</div>";
}
Reference
If it is a single dimensional array you can do this to keep it short and sweet:
foreach($items as $idx => $item) {
if (!isset($items[$idx+1])) {
print "I am last";
}
}
Here's another way you could do it:
$arr = range(1, 10);
$end = end($arr);
reset($arr);
while( list($k, $v) = each($arr) )
{
if( $n == $end )
{
echo 'last!';
}
else
{
echo sprintf('%s ', $v);
}
}
If I understand you, then all you need is to reverse the array and get the last element by a pop command:
$rev_array = array_reverse($array);
echo array_pop($rev_array);
You could also try this to make your query... shown here with INSERT
<?php
$week=array('one'=>'monday','two'=>'tuesday','three'=>'wednesday','four'=>'thursday','five'=>'friday','six'=>'saturday','seven'=>'sunday');
$keys = array_keys($week);
$string = "INSERT INTO my_table ('";
$string .= implode("','", $keys);
$string .= "') VALUES ('";
$string .= implode("','", $week);
$string .= "');";
echo $string;
?>
For SQL query generating scripts, or anything that does a different action for the first or last elements, it is much faster (almost twice as fast) to avoid using unneccessary variable checks.
The current accepted solution uses a loop and a check within the loop that will be made every_single_iteration, the correct (fast) way to do this is the following :
$numItems = count($arr);
$i=0;
$firstitem=$arr[0];
$i++;
while($i<$numItems-1){
$some_item=$arr[$i];
$i++;
}
$last_item=$arr[$i];
$i++;
A little homemade benchmark showed the following:
test1: 100000 runs of model morg
time: 1869.3430423737 milliseconds
test2: 100000 runs of model if last
time: 3235.6359958649 milliseconds
Another way to go is to remember the previous loop cycle result and use that as the end result:
$result = $where = "";
foreach ($conditions as $col => $val) {
$result = $where .= $this->getAdapter()->quoteInto($col.' = ?', $val);
$where .= " AND ";
}
return $this->delete($result);