Looping through a multidimensional associative array - php

I've been making an IRC bot in PHP. I've given different users specific access levels between 0 and 5. 0 being a guest and 5 being an admin.
I've been trying to write a command that when a user accesses it, it will send them a list of commands and syntax that they're allowed to use.
So far I have something like this
$array = array
(
"5" => $commands = array
(
"test" => $test2 = array
(
"trigger" => "!test",
"descrip" => "Just testing."
)
"test2" => $test3 = array
(
"trigger" => "!lol",
"descrip" => "another test."
)
)
);
I have no idea how to loop through it so that if ($accessLevel == 5) then show commands for $array[5(and below)]
At the end I want it to send out $array[5][command][trigger] : $array[5][command][descrip]
I don't necessarily need you to code it for me, just a push in the right direction would be helpful.

This should do it... (check the privilege level)
foreach($array as $level => $priv){
// check for privilege level
if($level >= $accessLevel){
// loop through privilege array
foreach($priv as $command => $list){
foreach($list as $trigger => $description)
}
}
}
}
On a side note, instead of using string keys for level you could use array indicies, and that would allow the combined outer foreach/if combination to be written as
for($i = $accessLevel; $i >= 0; $i--){
$priv = $array[$i];
//...
}

for ($i = 5; $i >= 0; --$i) {
//list commands for accesslevel $i
}

Something like this? (Prolly want to add newlines or delimiters)
foreach ($array[5] as $key=>$value) {
echo $key;
echo $value['trigger'];
echo $value['descrip'];
}

Related

Peek ahead when iterating an array of arrays in PHP

I have a mysql query object result which I want to parse through. Let's say the array looks like this.
$superheroes = array(
[0] => array(
"name" => "Peter Parker",
"email" => "peterparker#mail.com",
"age"=>"33",
"sex"=>"male",
),
[1] => array(
"name" => "jLaw",
"email" => "jlaw#mail.com",
"age"=>"22",
"sex"=>"female",
),
[2] => array(
"name" => "Clark Kent",
"email" => "clarkkent#mail.com",
"age"=>"36",
"sex"=>"male",
),
[3] => array(
"name" => "Gal Gadot",
"email" => "gal#mail.com",
"age"=>"22",
"sex"=>"female",
)
);
I want to iterate through this array, and while I am at each array, I want to look ahead in the next array, and find out the age difference between current male hero and next immediate female in the list. I found a lot of posts that talk about
1. array_keys
2. caching iterators,
3. prev, next, etc.
But all of them are talking about one dimensional arrays. Here Is what I tried
foreach ($superheroes as $key => $list){
if($list['sex']=="male"){
$currentHerosAge=$list['age'];
while($next=next($superheroes)){
if($next['sex']=="female"){
$diff=$currentHerosAge -$next['age'];
echo "Age diff: ".$diff;
break;
}
}
}
}
But when I try this, for array[0], next misses the array[1], and picks up array[3]. Not sure how to work this out.
You can use array_slice to slice array form the next key index and then look for the fist female age
$diff = [];
foreach($superheroes as $key => $male) {
if ($male['sex'] === 'female' ) continue;
// get the next key index
$nextKey = $key + 1;
if ( isset( $superheroes[ $nextKey ] ) ) {
// slice from the next key index
$nextSuperHeros = array_slice($superheroes, $nextKey);
foreach($nextSuperHeros as $k => $female) {
if ($female['sex'] === 'female') {
$diff[] = $male['age'] - $female['age'];
break;
}
}
}
}
A working Example
Hope this helps
Normally, you don't use a "lookahead", when iterating over the array. The common way would be to store the item of the last iteration and do the comparison on this element
$last_hero = false;
foreach ($superheroes as $hero) {
if ($last_hero) {
// do some stuff..
}
$last_hero = $hero;
}
If you really need a lookahead of more than one item, you wouldn't use a foreach loop.
for ($i = 0; $i < count($superheroes); $i++) {
// do sth. with $superheroes[$i]
if (...) {
for ($j = $i + 1; $j < count($superheroes); $j++) {
// do sth. with $superheroes[$j]
}
}
}
this code works, here's your solution for that situation (i will update explaining why) + editing the Clark - Gal part, one more comparison.
Execute it here if you like. this is a fancy version with echo's just to illustrate the running logic and what is happening inside the loops :) of course the final result can be much more simple.
<?php
$superheroes = [
[
"name" = "Peter Parker",
"email" = "peterparker#mail.com",
"age"="33",
"sex"="male",
],[
"name" = "jLaw",
"email" = "jlaw#mail.com",
"age"="22",
"sex"="female",
],[
"name" = "Clark Kent",
"email" = "clarkkent#mail.com",
"age"="36",
"sex"="male",
],[
"name" = "Gal Gadot",
"email" = "gal#mail.com",
"age"="22",
"sex"="female",
]
];
$length = count($superheroes);
$counterReset = 0;
while ($current = current($superheroes) )
{
$length -= 1;
if($current['sex']=="male"){
$currentHerosAge = $current['age'];
while($next = next($superheroes)){
$counterReset += 1;
if($next['sex']=="female"){
$diff=$currentHerosAge - $next['age'];
echo "\n C: ".$current['name']." to ".$next['name']." Age diff: ".$diff."\n";
break;
}
}
}
if($counterReset 0){
for($i = 0; $i < $counterReset; $i++){
prev($superheroes);
}
$counterReset = 0;
}
if($length == 0){
break;
}
next($superheroes);
}
current() next() prev() all act as pointers. Which means that every time you call them you control the movement of the assuming "head" of array or element you are calling. For this reason every time you move with next() you must make sure you also return back to the desired position in order to continue looping the regular loop :)
References next(), current(), prev() and reset()
execution logic
You declaration of the array or arrays was bringing a PHP Warning PHP Warning: Illegal offset type in /home/ on line 21 and was empty. For that reason I re-declared that way.

print all values in array from loop in a loop

I have an array created from loop which is returning the correct data
$ku = array();
$oid = array('id-ce-keyUsage');
if(isset($chain['tbsCertificate']['extensions'])) {
$count = count($chain['tbsCertificate']['extensions']);
for($i = 0; $i < $count; $i++) {
$count2 = count($chain['tbsCertificate']['extensions'][$i]['extnValue']);
for($j = 0; $j < $count2; $j++) {
if(array_key_exists('extnId', $chain['tbsCertificate']['extensions'][$i]) &&
in_array($chain['tbsCertificate']['extensions'][$i]['extnId'], $oid)) {
$value = $chain['tbsCertificate']['extensions'][$i]['extnValue'][$j];
$ku[] = $value;
}
}
}
}
print_r($ku);
The above code produces this, which is correct.
Array
(
[0] => keyEncipherment
[1] => digitalSignature
)
Array
(
[0] => cRLSign
[1] => keyCertSign
)
Array
(
[0] => cRLSign
[1] => keyCertSign
)
However, I would like to be able to print the values of $ku on their own, like so:
keyEncipherment, digitalSignature
cRLSign, keyCertSign
cRLSign, keyCertSign
I tried the following code but the results, and although the results look accurate, its actually adding the results of each iteration together rather then keeping them separate.
Here is the code im trying:
foreach ($ku as $val) {
$temp[] = "$val";
$key_usage = implode(', ', $temp);
}
echo $key_usage;
and here is the result:
keyEncipherment, digitalSignature
keyEncipherment, digitalSignature, cRLSign, keyCertSign
keyEncipherment, digitalSignature, cRLSign, keyCertSign, cRLSign, keyCertSign
Would appreciate some assistance. Happy to share more code if needed.
-UPDATE-
This code seems to help but hoping to find a better solution where i can just echo a string without []
$len=count($ku);
for ($i=0;$i<$len;$i++)
echo $ku[$i].', ';
You don't need to store value in to another array, as your value is array itself.
After the discussion in chat:
$new_ku = implode(',',$ku);
echo $new_ku;
try this code,
array_walk($ku, create_function('$k, $v', 'echo $v[0].", ".$v[1];'));
If you have PHP version >= 5.3 then you can use..
array_walk($ku, function($i, $v){ echo $v[0].", ".$v[1]; });

how to add letters of the name as array elements in php?

i am receiving the name from the $request in php.I want to do something like to add all the letters of the name in the array during the request e.g
$name=$_request['name'];
say $name='test';
i want to save it in an array in this format as array("t","e","s","t").
how can i do it ?
str_split is your friend.
$split_string = str_split($name);
It may be sufficient for you to access the string directly as an array, without the need to format the data:
$a = 'abcde';
echo $a[2];
Will output
c
However you won't be able to perform some array operations, such as foreach
see the php site
so it would be like
$name= 'test';
$arr1 = str_split($name);
would result in a array like:
Array
(
[0] => t
[1] => e
[2] => s
[3] => t
)
Here you go
$i = 0;
while(isset($name[$i])) {
$nameArray[$i] = $name[$i];
$i++;
}
Try this:
$letters = array();
for (int $i=0; $i < strlen($name); $i++){
$letters[] = $name[$i];
}
and you can access it with:
for (int $i=0; $i < strlen($letters); $i++){
$letters[$i];
}

Remove Array value

[0] => LR-153-TKW
[1] => Klaten
[2] => Rectangular
[3] => 12x135x97
I have an array looking like this. and I want to completely remove 12x135x97 to the mother array so how would i do this?
You can use unset($arr[3]);. It will delete that array index. Whenever you want to delete an array value, you can use PHP unset() method.
As you were asked into your comment:
basically i just want to remove all index that have "X**X" this pattern digit 'x' digit
Here is the code that you can use:
$arr = array("LR-153-TKW", "Klaten", "Rectangular", "12x135x97", "xxxx");
$pattern_matched_array = preg_grep("/^[0-9]+x[0-9]+x[0-9]*/", $arr);
if(count($pattern_matched_array) > 0)
{
foreach($pattern_matched_array as $key => $value)
{
unset($arr[$key]);
}
}
print_r($arr);
PHP has unset() function. You can use it for deleting a variable or index of array.
unset($your_var[3]);
See http://php.net/manual/en/function.unset.php
You have many options:
if you know the array key then you can do this
unset($arrayName[3]);
or if it's always at the end of your array
array_pop($arrayName);
this will remove the last value out of your array
Use unset, to find it you can do this:
for($i = 0; $i < count($array); $i++){
if($i == "12x135x97"){
unset($array[i]);
break;
}
}
Unless you know the key, in which case you can do:
unset($array[3]);
its not the most time efficient if you array is thousands of items long, but for this job it will suffice.
To turn it into a method, would make for better coding.
function removeItem($item){
for($i = 0; $i < count($array); $i++){
if($i == $item){
unset($array[i]);
break;
}
}
return $array;
}
and call it like:
removeItem("12x135x97");

Replace non-specified array values with 0

I want to replace all array values with 0 except work and home.
Input:
$array = ['work', 'homework', 'home', 'sky', 'door']
My coding attempt:
$a = str_replace("work", "0", $array);
Expected output:
['work', 0, 'home', 0, 0]
Also my input data is coming from a user submission and the amount of array elements may be very large.
A bit more elegant and shorter solution.
$aArray = array('work','home','sky','door');
foreach($aArray as &$sValue)
{
if ( $sValue!='work' && $sValue!='home' ) $sValue=0;
}
The & operator is a pointer to the particular original string in the array. (instead of a copy of that string)
You can that way assign a new value to the string in the array. The only thing you may not do is anything that may disturb the order in the array, like unset() or key manipulation.
The resulting array of the example above will be
$aArray = array('work','home', 0, 0)
A loop will perform a series of actions many times. So, for each element in your array, you would check if it is equal to the one you want to change and if it is, change it. Also be sure to put quote marks around your strings
//Setup the array of string
$asting = array('work','home','sky','door')
/**
Loop over the array of strings with a counter $i,
Continue doing this until it hits the last element in the array
which will be at count($asting)
*/
for($i = 0; $i < count($asting);$i++){
//Check if the value at the 'ith' element in the array is the one you want to change
//if it is, set the ith element to 0
if ($asting[$i] == 'work' || $asting[$i] == 'home')
$asting[$i] = 0;
}
Here is some suggested reading:
http://www.php.net/manual/en/language.types.array.php
http://www.php.net/manual/en/language.control-structures.php
But if you are struggling on stuff such as looping, you may want to read some introductory programming material. Which should help you really understand what's going on.
A bit other and much quicker way, but true, need a loop:
//Setup the array of string
$asting = array('bar', 'market', 'work', 'home', 'sky', 'door');
//Setup the array of replacings
$replace = array('home', 'work');
//Loop them through str_replace() replacing with 0 or any other value...
foreach ($replace as $val) $asting = str_replace($val, 0, $asting);
//See what results brings:
print_r ($asting);
Will output:
Array
(
[0] => bar
[1] => market
[2] => 0
[3] => 0
[4] => sky
[5] => door
)
An alternative using array_map:
$original = array('work','home','sky','door');
$mapped = array_map(function($i){
$exclude = array('work','home');
return in_array($i, $exclude) ? 0 : $i;
}, $original);
you may try array_walk function:
function zeros(&$value)
{
if ($value != 'home' && $value != 'work'){$value = 0;}
}
$asting = array('work','home','sky','door','march');
array_walk($asting, 'zeros');
print_r($asting);
You can also give array as a parameter 1 and 2 on str_replace...
Just a small point to the for loop. Many dont realize the second comparing task is done every new iteration. So if it was a case of big array or calculation you could optimize loop a bit by doing:
for ($i = 0, $c = count($asting); $i < $c; $i++) {...}
You may also want to see http://php.net/manual/en/function.array-replace.php for original problem unless the code really is final :)
Try This
$your_array = array('work','home','sky','door');
$rep = array('home', 'work');
foreach($rep as $key=>$val){
$key = array_search($val, $your_array);
$your_array[$key] = 0;
}
print_r($your_array);
There are a few techniques on this page that make zero iterated function calls -- which is good performance-wise. For best maintainability, I recommend separating your list of targeted string as a lookup array. By modifying the original array values by reference, you can swiftly replace whole strings and null coalesce non-targeted values to 0.
Code: (Demo)
$array = ['work', 'homework', 'home', 'sky', 'door'];
$keep = ['work', 'home'];
$lookup = array_combine($keep, $keep);
foreach ($array as &$v) {
$v = $lookup[$v] ?? 0;
}
var_export($array);
Output:
array (
0 => 'work',
1 => 0,
2 => 'home',
3 => 0,
4 => 0,
)
You can very easily, cleanly extend your list of targeted strings by merely extending $keep.
If you don't want a classic loop, you can use the same technique without modifying the original array. (Demo)
var_export(
array_map(fn($v) => $lookup[$v] ?? 0, $array)
);
this my final code
//Setup the array of string
$asting = array('work','home','sky','door','march');
/**
Loop over the array of strings with a counter $i,
Continue doing this until it hits the last element in the array
which will be at count($asting)
*/
for($i = 0; $i < count($asting); $i++) {
//Check if the value at the 'ith' element in the array is the one you want to change
//if it is, set the ith element to 0
if ($asting[$i] == 'work') {
$asting[$i] = 20;
} elseif($asting[$i] == 'home'){
$asting[$i] = 30;
}else{
$asting[$i] = 0;
}
echo $asting[$i]."<br><br>";
$total += $asting[$i];
}
echo $total;

Categories