For instance, i have a 2 list of values that has no relevance with each elements. I'm planning to put this values manually.
$a1 = 'red';
$a2 = '007';
$a3 = 'gun';
$a4 = 'apple';
$b1 = 'poison';
$b2 = 'movie';
$b3 = 'man';
$b4 = 'store';
echo $a.' with '.$b
I want an output like:
red with poison
007 with movie
gun with man
apple with store
So I want $an displayed with $bn. I have thought of using a for loop, but I don't know how to do it (I'm really new to PHP...)
Any suggestions? any help would be great. thanks in advance!
Use arrays :
$a[0] = 'red';
$a[1] = '007';
$a[2] = 'gun';
$a[3] = 'apple';
$b[0] = 'poison';
$b[1] = 'movie';
$b[2] = 'man';
$b[3] = 'store';
foreach($a as $key=>$value)
{
echo $value.' with '.$b[$key];
}
I think the simplest is to use a associative array and foreach like this:
foreach (array("red" => "poison",
"007" => "movie",
"gun" => "man",
"apple" => "store") as $a => $b) {
echo "$a with $b\n";
}
change your setup to an array
$a[1] = 'red';
$a[2] = '007';
$a[3] = 'gun';
$a[4] = 'apple';
$b[1] = 'poison';
$b[2] = 'movie';
$b[3] = 'man';
$b[4] = 'store';
then use a for loop
for($n=0;$n<sizeof($a);$n++){
echo $a[$n] . ' with ' . $b[$n];
}
with this method you can call any part of the variable with its known number at any time elsewhere in the script, such as:
echo $b[2];
This is an explanation on the for loop.
for() This calls the loop and is limited by { and }
The arguments in the loop start with your starter.
In my case I used $n. I set $n to 0 to give the loops somewhere to start from.
The next part of the loop is how many times you want it iterated in comparison to your start variable. This is usually dependent on the size of an array but can also be a number. The argument I created here to determine the iterations. sizeof() is another function within php to get the number of elements within an array or variable (or i think it can do file sizes too). I am telling it to make sure that as long as $n is less than the size of the variable to keep looping. You normally want a loop to end after a while else pages take forever to load.
Finally you add the thing at the end to increase the counter so to speak. This can be anything once again but using $n++ means it increases the value of $n by 1 each time until the end of the loop
You can use arrays:
//that's how you add elements to an array
$a[] = 'red';
$a[] = '007';
$a[] = 'gun';
$a[] = 'apple';
$b[] = 'poison';
$b[] = 'movie';
$b[] = 'man';
$b[] = 'store';
//and this is how you read from an array
for($i=0; $i<count($a); $i++){
echo $a[$i].' with '.$b[$i] . "\n";
}
for (var $i = 1; $i <= 4; $i++) {
echo ${"a".$i} . " with " . ${"b".$i};
}
see http://php.net/manual/en/language.variables.variable.php
Related
I have an array for example
$a = [1,2,3,4,5];
From this $a, how to take last one and set it first like [5,1,2,3,4]
And how do I take last two arrays to make it like [4,5,1,2,3]
You can combine using array_pop(), which pops the last element of the array out, and array_unshift() to push it to the front of the array. You can create a simple function for this,
function array_pop_unshift($array) {
array_unshift($array, array_pop($array));
return $array;
}
Then use it as
$a = [1,2,3,4,5];
$new = array_pop_unshift($a);
print_r($new); // [5,1,2,3,4]
To continue shifting it, just call the function again until you're done, for instance through a for loop,
$a = [1,2,3,4,5];
for ($i = 0; $i < 2; $i++) {
$new = array_pop_unshift($a);
}
print_r($new); // [4,5,1,2,3]
Live demo at https://3v4l.org/CoJZZ
If you want to avoid the cost of several array_unshift and array_pop, you can build a generator that plays with the array internal pointer.
If you really need a result array, use iterator_to_array() to create it:
$a = range(1,5);
function rotate(&$array, $step = 1) {
$length = count($array);
end($array);
while ($step--)
prev($array);
while ($length--) {
next($array);
if (key($array) === null)
reset($array);
yield current($array);
}
}
print_r(iterator_to_array(rotate($a, 2))); // [4,5,1,2,3]
demo
Note that the rotate() generator uses a reference to avoid the array copy but doesn't modify the orginal array: it only moves the array pointer n times (where n is the array length) from the choosen position. When the array pointer is out of the array (key() returns null) the array pointer is reseted. In other words it stays efficient even with a large array and many rotations (what I have called "step" in the code).
You are actually doing right rotation, not left. Anyway, here are functions for doing both of them. They are probably not the most efficient but they are short in code and pretty self-explanatory:
<?php
function rotateLeft($array, $times) {
for($i=0; $i<$times; $i++){
$array[] = array_shift($array);
}
return $array;
}
function rotateRight($array, $times) {
for($i=0; $i<$times; $i++){
array_unshift($array, array_pop($array));
}
return $array;
}
$a = [1,2,3,4,5];
$a = rotateRight($a, 1);
print_r($a);
?>
to take last one and set it first This is known as right rotation.
And
$k is the number of units the shifting should be. $a is the array.
for($x=0; $x < $k; $x++){
//remove last element
$last = array_pop($a);
//push last element to the beginning
array_unshift($a, $last);
}
array_pop() pops and returns the value of the last element of array, shortening the array by one element.
https://www.php.net/manual/en/function.array-pop.php
array_unshift() prepends passed elements to the front of the array
https://www.php.net/manual/en/function.array-unshift.php
You could create a function that takes two arguments $k(number of rotations), $a (the array) and returns the array after performing right rotation $k times.
function rotateRight($a, $k){
for($x=0; $x < $k; $x++){
//remove last element
$last = array_pop($a);
//push last element to the beginning
array_unshift($a, $last);
}
return $a;
}
And then call it accordingly.
Example:
$a = [1,2,3,4,5];
$a_one_shift = rotateRight($a, 1);
// [5,1,2,3,4];
$a_two_shift = rotateRight($a_one_shift, 1);
// [4,5,1,2,3];
Or you could pass 2 to directly get the array after two right rotations.
$a_new = rotateRight($a, 2);
// [4,5,1,2,3];
Rather than making iterated calls of array_pop() and array_unshift(), use an efficient, elegant approach that makes fewer function calls and has the lowest possible time complexity. Using early returns prevents making needless function calls for the same result.
Code: (Demo)
function popUnshift(array $indexedArray, int $popShiftsCount): array
{
$count = count($indexedArray);
if ($count < 2) {
return $indexedArray; // array cannot be rotated
}
$remainder = $popShiftsCount % $count;
if (!$remainder) {
return $indexedArray; // sought rotation is the original order
}
return array_merge(
array_splice($indexedArray, -$remainder),
$indexedArray
);
}
Disclosure: This answer was built on the CodeReview page (Codility cyclic rotation solution in PHP) where I offered this snippet in my review.
//$A input array, $K rotation times
function solution($A, $K) {
$new = array();
for($j=1;$j<=$K;$j++)
{
if(count($new)>0)
$A = $new;
for($i=0;$i<count($A);$i++)
{
if($i==0)
$new[$i] = $A[count($A)-1];
else
$new[$i] = $A[$i-1];
}
}
return $new;}
I have been reading through the manual to find a function that does what I want but I ended up doing it myself. I want to compare two arrays and calculate the difference between the keys. Or more practically analyse the difference in order of the values.
I have done this as follows, but I have a feeling this can be done better.
if anyone has an idea how to improve this please let me know becasue im eager to improve.
<?php
$goodarray = array(300,250,200,150,100);
$usersupliedarray = array(250,300,200,150,100); // first two spots are wrong
$score = count($goodarray);
foreach($usersupliedarray as $key => $value){
$arraykey = array_search($value, $goodarray);
$difference = abs($key-$arraykey);
$score = $score + $difference;
echo "$value $goodarray[$key] ($difference = $score) <hr />";
}
array_map with a void callback can come in handy here, for example,
$a = array(300,250,200,150,100);
$b = array(250,300,200,150,100);
$faults = 0;
foreach(array_map(null, $a, $b) as $x)
$faults += $x[0] != $x[1]; // x[0] is $a element, x[1] is $b
print $faults; // 2
UPD: if you want to compute distances between equal elements, and not just count differences, your original code looks just fine to me. One improvement which can be made is to get rid of inefficient array_search and to use an "inverted index" of the first array instead:
foreach($a as $pos => $val)
$inv[$val] = $pos;
or just
$inv = array_flip($a);
and then
foreach($b as $pos => $val)
$score += abs($pos - $inv[$val]);
I know basic examples about foreach to for loop and while loop since I was begin coding I didn't paying attention from the speed of executing a script which it is very very important since then I keep converting all my for each statement to for loop. If it's comes to array i'm quite confused -_-. I know it gives me down vote posting this. LIKE I'd rather let people figure things out for myself.
I just need a bit of guide using a for loop statement. How can I convert the following foreach loop to for loop/ while loop statement?
like what I seen on phpbenchmark.com as
$i = 0; while($i < 1000000) ++$i;
for($i = 0; $i < 1000000; ++$i);
CODE:
<?php
$user['001'] = 'A';
$user['002'] = 'B';
$user['003'] = 'C';
$user['004'] = 'D';
foreach($user as $id => $name)
{
echo '<br>Id='.$id.'Name='.$name;
}
?>
thanks alot.
EXPECTED OUTPUT LIKE foreach output:
Id=001Name=A
Id=002Name=B
Id=003Name=C
Id=004Name=D
also what if I have an array keys like
$user['AAA'] = 'A';
$user['BBB'] = 'B';
$user['CCC'] = 'C';
$user['DDD'] = 'D';
it will output as:
Id=AAAName=A
Id=AAAName=B
Id=AAAName=C
Id=AAAName=D
The for and while loops you show are simply incrementing a number, which you can use to access elements of an array if the keys of that array are equivalent to those numbers. In other words, for or while loops have nothing to do with arrays as such, you're just using a number as a key to an array.
If your array keys are not simple continuous integers, this is more problematic. You could try to construct the correct keys from your $i variable, but why? You should just iterate explicitly over the keys of the array, for which foreach is perfect. You can also do it with each or any number of other complicated ways:
while (list($key, $value) = each($array)) {
...
}
But I doubt it's going to be significantly faster than a foreach.
Something like this...
<?php
$user['001'] = 'A';
$user['002'] = 'B';
$user['003'] = 'C';
$user['004'] = 'D';
while (current($user)) {
echo '<br>Id='.key($user).'Name='.$user[key($user)];
next($user);
}
try this
$user['001'] = 'A';
$user['002'] = 'B';
$user['003'] = 'C';
$user['004'] = 'D';
$keys = array_keys($user);
$length = sizeof($user);
for($i=0; $i<$length; $i++) {
echo 'id: '.$keys[$i].' value: '.$user[$keys[$i]].'<br />';
}
do you wanted something like this?
$length = count($user);
for ($i = 0; $i < $length; $i++) {
print $user[$i];
}
EDIT: or something like this?
$user = array ( '001' => 'A',
'002' => 'B',
'033' => 'C' );
while( list ( $id, $name) = each ( $user) )
{
echo '<br>Id=' .$id. 'Name='.$name;
}
EDIT:also works with you r AAA = A etc case
I have 2 arrays, both are multidimensional with same number of elements and same values, which are on different positions (those values are actually ID-s from my database, so one ID appears only once). How can I sort second array with values which are in first array?
For example - if first array looks like:
$array1[0][0] = 1;
$array1[0][x] = it doesn't matter what's here
$array1[1][0] = 4;
$array1[1][x] = it doesn't matter what's here
$array1[2][0] = 3;
$array1[2][x] = it doesn't matter what's here
...
how to sort second array so it would have same values as array1 on indexes [0][0], [1][0], [2][0], etc.
How I could solve problem is:
$i=0
while ($i < (count($array1)-2)){ // * check down
$find_id = $array1[$i][0];
// here I need to search for index of that ID in other array
$position = give_index($find_id, $array2);
// swapping positions
$temp = array2[$i][0];
$array2[$i][0] = $array2[$position][0];
$array2[$position][0] = $temp;
// increasing counter
i++;
}
function give_index($needle, $haystack){
for ($j = 0, $l = count($haystack); $j < $l; ++$j) {
if (in_array($needle, $haystack[$j][0])) return $j;
}
return false;
}
*There is only -2 because indexes start from 0 and also for the last element you don't need to check since it would be automatically sorted by last iteration of while-loop.
I don't find this solution good as I think that this is quite simple issue (maybe it's not even correct). Is there easier way in PHP that I'm missing?
This is the most efficient way I can think of:
function swap(&$a, &$b) {
$t = $a;
$a = $b;
$b = $t;
}
function find_index($id, $array, $from = 0) {
$index = false;
for ($i = $from, $c = count($array); $i < $c; $i++) {
if ($array[$i][0] == $id) {
$index = $i;
break;
}
}
return $index;
}
for ($i = 0, $c = count($array1); $i < ($c - 2); $i++) {
if ($array1[$i][0] != $array2[$i][0]) {
$fi = find_index($array1[$i][0], $array2, $i);
swap($array2[$i][0], $array2[$fi][0]);
}
}
What changes from yours?
I've defined a swap() function in order to swap any variable. That doesn't cost anything and makes everything look nicer. Also you can reuse that function later if you need to.
In the find_index (give_index in your code) we stop the loop once we find the correct index. Also we avoid the cost of an in_array function call.
We modified the find_index function to start only from the part of the array we haven't checked yet. Leading to a way more efficient way of scan the array.
In the for loop (a while loop was just wrong there) we stored the count of the array once, avoiding multiple calls.
Also we swap the $array2 values only if they are in the wrong place.
Other improvements
If you know anything else of the $array2 array you can make this even more performant. For example if you know that indexes are alternated like in $array1 you can change the main for loop from:
for ($i = 0, $c = count($array1); $i < ($c - 2); $i++) {
to
for ($i = 0, $c = count($array1); $i < ($c - 2); $i+2) {
(notice the $i+2 at the end) And you could do that in the find_index function as well.
Look into usort (http://php.net/manual/en/function.usort.php).
It provides a simple way to sort arrays using a user provided comparison function.
I need to combine two foreach statement into one for example
foreach ($categories_stack as $category)
foreach ($page_name as $value)
I need to add these into the same foreach statement
Is this possible if so how?
(I am not sure I have understood your question completely. I am assuming that you want to iterate through the two lists in parallel)
You can do it using for loop as follows :
$n = min(count($category), count($value));
for($c = 0; $c < $n; $c = $c + 1){
$categories_stack = $category[$c];
$pagename = $value[$c];
...
}
To achieve the same with foreach you need a function similar to Python's zip() function.
In Python, it would be :
for categories_stack, pagename in zip(categories, values):
print categories_stack, pagename
Since PHP doesn't have a standard zip() function, you'll have to write such a function on your own or go with the for loop solution.
You can do nested foreachs if that's what you want. But without knowing more of your data, it's impossible to say if this helps:
foreach ($categories_stack as $category) {
foreach ($page_name as $value) {
}
}
Probably you want to print out all pages in a category? That probably won't work, so can you give a bit more info on how the arrays look like and relate to each other?
This loop will continue to the length of the longest array and return null for where there are no matching elements in either of the arrays. Try it out!
$a = array(1 => "a",25 => "b", 10 => "c",99=>"d");
$b = array(15=>1,5=>2,6=>3);
$ao = new ArrayObject($a);
$bo = new ArrayObject($b);
$ai = $ao->getIterator();
$bi = $bo->getIterator();
for (
$ai->rewind(),$bi->rewind(),$av = $ai->current(),$bv = $bi->current();
list($av,$bv) =
array(
($ai->valid() ? $ai->current() : null),
($bi->valid() ? $bi->current() : null)
),
($ai->valid() || $bi->valid());
($ai->valid() ? $ai->next() : null),($bi->valid() ? $bi->next() : null))
{
echo "\$av = $av\n";
echo "\$bv = $bv\n";
}
I cannot really tell from the question exactly how you want to traverse the two arrays. For a nested foreach you simply write
foreach ($myArray as $k => $v) {
foreach ($mySecondArray as $kb => $vb {
}
}
However you can do all sorts of things with some creative use of callback functions. In this case an anonymous function returning two items from each array on each iteration. It's then easy to use the iteration value as an array or split it into variables using list() as done below.
This also has the added benefit of working regardless of key structure. I's purely based on the ordering of array elements. Just use the appropriate sorting function if the elements are out of order.
It does not worry about the length of the arrays as there is no error reported, so make sure you keep an eye out for empty values.
$a = array("a","b","c");
$b = array(1,2,3);
foreach (
array_map(
create_function(
'$a,$b', 'return array($a,$b);'
)
,$a,$b
)
as $value
)
{
list($a,$b) = $value;
echo "\$a = $a\n";
echo "\$b = $b\n";
}
Output
$a = a
$b = 1
$a = b
$b = 2
$a = c
$b = 3
Here's another one for you that stops on either of the lists ending. Same as using min(count(a),count(b). Useful if you have arrays of same length. If someone can make it continue to the max(count(a),count(b)) let me know.
$ao = new ArrayObject($a);
$bo = new ArrayObject($b);
$ai = $ao->getIterator();
$bi = $bo->getIterator();
for (
$ai->rewind(),$bi->rewind();
$av = $ai->current(),$bv=$bi->current();
$ai->next(),$bi->next())
{
echo "\$av = $av\n";
echo "\$bv = $bv\n";
}
This is where the venerable for loop comes in handy:
for(
$i = 0,
$n = sizeof($categories_stack),
$m = sizeof($page_name);
$i < $n && $i < $m;
$i++
) {
$category = $categories_stack[$i];
$value = $page_name[$i];
// do stuff here ....
}
Surely you can just merge the arrays before looping?
$data = array_merge($categories_stack, $page_name);
foreach($data AS $item){
...
}
Do the array elements have a direct correspondence with one another, i.e. is there an element in $page_name for each element in $categories_stack? If so, just iterate over the keys and values (assuming they have the same keys):
foreach ($categories_stack as $key => $value)
{
$category = $value;
$page = $page_name[$key];
// ...
}
Could you just nest them with variables outside the scope of the foreach, or prehaps store the content as an array similar to a KVP setup? My answer is vague but I'm not really sure why you're trying to accomplish this.