order data based on an array - php

I have an array:
$order = array(2,0,1)
I also have three text variables
$a, $b, $c
they are each represented by a number $a is 0, $b is 1 and $c is 2
I want to add the variables to a text variable ($holder) in the order set by the array
so if the array is (2,0,1) then
$holder = $c.$a.$b
When $order changes I want the order in $holder to change to match.
I can make this work but it seems a really rubbish way of doing it so I wondered if anyone had a better way:
$holder ="";
$order = array(2,0,1)
for($x=0;$x<count($holder);$x++){
switch ($order)
case 0:
$holder .= $a;
break;
case 1:
$holder .=$b;
break;
case 2:
$holder .=$c;
break;
}
thanks
Update
Thanks for the replies they really made me think about the best way to achieve the result. My own solution might work but that's not enough the code needs to be good too. I think it's important to produce good code not just okay code so thanks for the help.

Probably not the fastest, but using some of the array_ functions. This inverts the order to make the order values the keys, then uses array_replace() to take the values from the corresponding point in an array of the parameters. Then just implode() the result...
$order = array(2,0,1);
$a="1";
$b="2";
$c="3";
echo implode(array_replace(array_flip($order), [ $a, $b, $c ]));
gives
312

Normal array contains key starting from 0. You can use that concept and assign your text variable to array based on their representation.
Like $a represent 0, so put its value to index 0 of array and so on.
Now you can easily access these values by accessing array index.
$a = 'X';
$b = 'Y';
$c = 'Z';
$arr = [$a, $b, $c];
$order = [2,0,1];
$text = '';
foreach($order as $key){
$text .= $arr[$key];
}
echo $text;
Output:
ZXY

A short PHP 7.4+ solution, using implode, array_map and arrow functions:
$a = 'a';
$b = 'b';
$c = 'c';
$values = [$a, $b, $c];
$order = [2, 0, 1];
$holder = implode(array_map(fn($index) => $values[$index] ?? null, $order)); // "cab"
Demo

Another version, hope to match with your idea.
$order = array(1,0,2);
$var = array(
0 => "a",
1 => "b",
2 => "c"
);
$holder = '';
foreach( $order as $item ){
$holder .= $var[$item];
}
echo $holder;

Related

Sort an array based on another array in php?

according to this answer -> Sort an Array by keys based on another Array?, I use this function to get my another array sorted:
function sortArrayByArray($array,$orderArray) {
$ordered = array();
foreach($orderArray as $key) {
if(array_key_exists($key,$array)) {
$ordered[$key] = $array[$key];
unset($array[$key]);
}
}
return $ordered + $array;
}
at first, I have my code like this and it works fine
$array1 = array("a","b","c");
$array2 = array("2","5","1");
$array3 = array("2","5","1");
rsort($array3); //5,2,1
for($i=0;$i<3;$i++){
$customer1[$array2[$i]] = $array1[$i];
}
$properOrderedArray1 = sortArrayByArray($customer1, $array3);
print_r($properOrderedArray1);
but when I use some logic math like multiply, it gets any errors like it said there is data type float
//multiply
$a = 100000*100000;
$b = 200000*200000;
$c = 300000*300000;
$array1 = array("a","b","c");
$array2 = array($a,$b,$c);
$array3 = array($a,$b,$c);
rsort($array3); //5,2,1
for($i=0;$i<3;$i++){
$customer1[$array2[$i]] = $array1[$i];
}
$properOrderedArray1 = sortArrayByArray($customer1, $array3);
print_r($properOrderedArray1);
var_dump($array2);
THE ERROR: Warning: array_key_exists(): The first argument should be either a string or an integer
so any solution for this problem?
Thanks.
As stated, you will have to convert your floats to strings. I guess you can alter your function to something like this to make it work:
function sortArrayByArray($array,$orderArray) {
$ordered = array();
foreach($orderArray as &$key) {
if (!is_int($key))
$key = number_format($key,0,'.','');
if(array_key_exists($key,$array)) {
$ordered[$key] = $array[$key];
unset($array[$key]);
}
}
return $ordered + $array;
}
The problem about doing it this way is that you lose precision in your float value. In a 64-bit system all these values
$a = 9223372036854775808;
$b = 9223372036854775809;
$c = 9223372036854775810;
will be converted into the same float(9.2233720368548E+18), and converting it to a string will give string(19) "9223372036854775808". As long as your indexes that you use for sorting have significant numbers in the upper range of the number it can work, but it's not a safe way of sorting.
Basically what i written in the comment is true as i just checked in the manual: http://php.net/manual/en/language.types.integer.php
$large_number = 2147483647; //treated as int
$large_number = 2147483648; //treated as float since it is too large for an integer
So the solution to your problem is to limit the indices to the max value of integers.
OR to convert the floats to strings, but i would NOT recommend that, but sadly that seems to be the only way to achieve what you are trying to do.

I want to put specific values in for loop

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

Array keys ,get array values ,then comma separate

I have :
$a = array(
0=>'you',
1=>'will',
2=>'be',
3=>'so',
4=>'happy',
5=>'in'
);
$b = array(
0=>'1',
1=>'4',
2=>'5'
); // (KEYS:1,4,5)
I want out the values of $a that matches $b's keys;
so $val would be willhappyin.
And then comma-separate them.. like: will,happy,in without comma after last one.
How can i do this ? :)
$string = implode(",", array_intersect_key($a, array_flip($b)));
EXPLANATION:
array_flip switches the values of $b to keys.
array_intersect_key takes only the entries in $a that are also present in $b.
implode joins the resulting array values together by comma.
$c = array();
foreach($b as $key)
{
$c[] = $a[$key]
}
echo implode(",",$c);
$out_arr = array();
foreach ($b as $k => $v) {
array_push($out_arr, $a[$v]);
}
return join($out_arr, ',');

Array combine into associative array

I need to add the values of an associative array to another one.
$a = array(4=>2,5=>5);
$b = arrray(array(0=>0,1=>4,2=>10,3=>1000),array()...);
What I'm expecting to get is a third array ($c) like the one below where the content of $b follows the content of $a:
$c = array(array(4=>2,5=>5,0=>0,1=>4,2=>10,3=>1000),array(4=>2,5=>5....));
This is what I've written (not working):
$c = array();
foreach ($possible_opp_action as $sub) {
$c[] = array_push($to_merge,array_values($sub));
}
$a = array(4=>2,5=>5);
$b = array(array(0=>0,1=>4,2=>10,3=>1000),
array(0=>0,1=>40,2=>100,3=>2000),
array(4=>10)
);
$c = array();
foreach($b as $tmp) {
$c[] = $a+$tmp;
}
var_dump($c);
Unlike array_merge, this will maintain numeric keys... but watch out for duplicate keys
$c = array();
foreach ($b as $bb) {
$c[] = array_merge($a,$bb);
}
If you do not need $b in original form:
<?php
$a = array(4=>2,5=>5);
$b = array(array(0=>0,1=>4,2=>10,3=>1000),array());
foreach ($b as &$ref) {
$ref = $a + $ref;
}
var_dump($b);
Otherwise:
<?php
$a = array(4=>2,5=>5);
$b = array(array(0=>0,1=>4,2=>10,3=>1000),array());
$c = array();
foreach ($b as &$ref) {
$c[] = $a + $ref;
}
var_dump($c);
You need array_merge.
http://us.php.net/manual/en/function.array-merge.php
Note the handling of duplicate keys:
Merges the elements of one or more arrays together so that the values of one are appended to the end of the previous one. It returns the resulting array.
If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. If, however, the arrays contain numeric keys, the later value will not overwrite the original value, but will be appended.
Values in the input array with numeric keys will be renumbered with incrementing keys starting from zero in the result array.
EDIT:
I may have not read the question right - please clarify...
Do you want all the array items in a single array, or an array with the original arrays as items in it (an array of arrays)?
IE:
c = array(a=a, b=b, c=c, etc.) <- can be done with array_merge($a, $b, $c, etc)
vs
c = array(
b = array(a=a, b=b, c=c, etc),
a=array(d=d, e=e, etc.)
) <- should be done by just concatenating the next array on the end like this (and skip the $c altogether):
$c[] = $b;
$c[] = $a;
//or
$c = array();
foreach ($possible_opp_action as $sub) {
$c[] = $sub;
}
try
$c = array_merge($b, $a)
help in http://php.net/manual/es/function.array-merge.php

foreach php statement

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.

Categories