Searching and replacing arrays in arrays - php

My title is a bit confusing. I will try to explain better what I want to do.
I have an array with other arrays:
array (size=16)
0 =>
array (size=4)
'value' => string 'apple.png' (length=9)
'x' => int 3
'y' => int 4
'status' => boolean false
1 =>
array (size=4)
'value' => string 'apple.png' (length=9)
'x' => int 2
'y' => int 3
'status' => boolean false
2 =>
array (size=4)
'value' => string 'cake.png' (length=8)
'x' => int 3
'y' => int 1
'status' => boolean false
Then I have a form with hidden inputs:
'<input type="hidden" value="x:'.$i.';y:'.$j.'" name="coords"/>';
When the form is submitted I get the value and extract the coordinates. Then I do a loop.
foreach($this->mapBoard as $block)
{
if($block['x'] == $x && $block['y'] == $y)
{
$block['status'] = true;
return $block;
}
else
{
continue;
}
}
The main array is called 'mapBoard'. My question is how when I find the right array element, to change its value of the status key. And put it back in mapBoard.

Try,
foreach($this->mapBoard as $key => $block)
{
if($block['x'] == $x && $block['y'] == $y)
{
$this->mapBoard[$key]['status'] = true;
return $block;
}
else
{
continue;
}
}

PHP's foreach by default makes a copy of the array it is iterating on, so we will have to manually stuff data back in when modified.
Here is a simple tweak to your code to do it
// For arrays foreach will give us the loop iteration in `i` while using $i => $block
foreach($this->mapBoard as $i=>$block)
{
if($block['x'] == $x && $block['y'] == $y)
{
$block['status'] = true;
// we know i is the position, so stuff it back in
$this->mapBoard[$i] = $block;
return $block;
}
else
{
continue;
}
}

You can return array key in place of $block['status'] = true; , after that you update status according to array key.

Related

PHP comparing all value inside column of multidimensional array with variable

I have a multidimensional array and a variable to compare:
$var = 1;
$arr = array(
0 => array(
'id' => 5
'NumberAssigned' = 1
),
n => array(
'id' => 22
'NumberAssigned' = 1
)
)
I want to compare all of the value inside the NumberAssigned column in the multidimensional array with the variable, if all of the value in column match with the variable then $var = $var+1. What is the solution?
One option is using array_column to make the multidimensional array into a simple array. Use array_unique to get the unique values. If there are only 1 unique value and the value is the same with $var, all NumberAssigned are the same with $var
$var = 1;
$arr = array(
0 => array(
'id' => 5,
'NumberAssigned' => 1
),
1 => array(
'id' => 22,
'NumberAssigned' => 1
),
2 => array(
'id' => 23,
'NumberAssigned' => 1
),
);
$num = array_unique(array_column($arr,'NumberAssigned'));
if( count($num) === 1 && $num[0] === $var ) $var++;
No need to loop.
Use array_column to get all values and remove duplicates with array_unique.
If the var is in the array and the count is 1 then all values match var.
$narr = array_unique(array_column($arr, "NumberAssigned"));
If(in_array($var, $narr) && count($narr) == 1){
$var++;
}Else{
// They are not all 1
}
Echo $var;
https://3v4l.org/k08NI
You can force uniqueness by using the targeted column as first level keys. As a concise technique when you don't need microoptimization, you can use:
if (count(array_column($arr, null, 'NumberAssigned')) < 2)
// true if $arr is empty or all values in column are the same
This won't be technically fastest. The fastest algorithm would allow an early return before iterating the entire set of data in the column.
function allValuesAreSame($array, $columnName) {
$result = [];
foreach ($array as $row) {
$result[$row[$columnName]] = null;
if (count($result) > 1) {
return false;
}
}
return true; // also true if $array is empty
}

set array key pointer inside a foreach according to a variable php [duplicate]

Im trying to build a little site using XML instead of a database.
I would like to build a next and prev button which will work relative to the content I have displayed.
I found the php function next() and prev() as well as current() but I do not know how to set the pointer to a specific position to be able to navigate relative to the current page.
$list=array('page1','page2','page3')
eg if im displaying contents of page2 how could I tell php i am at $list[1] so that next($list) shows page3?
Thanks in advance
If your array is always indexed consistently (eg. 'page1' is always at index '0'), it's fairly simple:
$List = array('page1', 'page2', 'page3', 'page4', 'page5');
$CurrentPage = 3; // 'page4'
while (key($List) !== $CurrentPage) next($List); // Advance until there's a match
I personally don't rely on automatic indexing because there's always a chance that the automatic index might change. You should consider explicitly defining the keys:
$List = array(
'1' => 'page1',
'2' => 'page2',
'3' => 'page3',
);
EDIT: If you want to test the values of the array (instead of the keys), use current():
while (current($List) !== $CurrentPage) next($List);
Using the functions below, you can get the next and previous values of the array.
If current value is not valid or it is the last (first - for prev) value in the array, then:
the function getNextVal(...) returns the first element value
the function getPrevVal(...) returns the last element value
The functions are cyclic.
function getNextVal(&$array, $curr_val)
{
$next = 0;
reset($array);
do
{
$tmp_val = current($array);
$res = next($array);
} while ( ($tmp_val != $curr_val) && $res );
if( $res )
{
$next = current($array);
}
return $next;
}
function getPrevVal(&$array, $curr_val)
{
end($array);
$prev = current($array);
do
{
$tmp_val = current($array);
$res = prev($array);
} while ( ($tmp_val != $curr_val) && $res );
if( $res )
{
$prev = current($array);
}
return $prev;
}
Using the functions below, you can get the next and previous KEYs of the array.
If current key is not valid or it is the last (first - for prev) key in the array, then:
the function getNext(...) returns 0 (the first element key)
the function getPrev(...) returns the key of the last array element
The functions are cyclic.
function getNext(&$array, $curr_key)
{
$next = 0;
reset($array);
do
{
$tmp_key = key($array);
$res = next($array);
} while ( ($tmp_key != $curr_key) && $res );
if( $res )
{
$next = key($array);
}
return $next;
}
function getPrev(&$array, $curr_key)
{
end($array);
$prev = key($array);
do
{
$tmp_key = key($array);
$res = prev($array);
} while ( ($tmp_key != $curr_key) && $res );
if( $res )
{
$prev = key($array);
}
return $prev;
}
The internal array pointer is mainly used for looping over an array within one PHP script. I wouldn't recommend using it for moving from page to page.
For that, just keep track of the page number and the page size (number of items per page). Then, when you're loading another page, you can use them to decide which array items to show. For example:
$pageNum = $_GET["pageNum"];
$pageSize = 10;
$startIndex = ($pageNum - 1) * $pageSize;
$endIndex = ($startIndex + $pageSize) - 1;
(or something similar)
another aproach without loops or search.
list($prev,$next) = getPrevNext($oObjects,$sCurrentKey);
function getPrevNext($aArray,$key){
$aKeys = array_keys($aArray); //every element of aKeys is obviously unique
$aIndices = array_flip($aKeys); //so array can be flipped without risk
$i = $aIndices[$key]; //index of key in aKeys
if ($i > 0) $prev = $aArray[$aKeys[$i-1]]; //use previous key in aArray
if ($i < count($aKeys)-1) $next = $aArray[$aKeys[$i+1]]; //use next key in aArray
return array($prev,$next);
}
I use this code for set internal pointer with key of array.
reset($List);
while (key($List) !== $id && key($List) !== null) next($List);
if(key($List) === null) end($List);
After that you can use prev() or next().
Update follow notice from #VaclavSir
Try this
public function getNextVal(&$array, $curr_val){
foreach($array as $k=>$v){
if($v['your_key'] == $curr_val){
if(isset($array[$k+1]))
return $array[$k+1];
else
return $array[0];
}
}
}
public function getPrevVal(&$array, $curr_val){
foreach($array as $k=>$v){
if($v['your_key'] == $curr_val){
if(isset($array[$k-1]))
return $array[$k-1];
else
return end($array);
}
}
}
for array like this:
array (size=3)
0 =>
array (size=11)
'id' => string '21' (length=2)
'cat' => string '1' (length=1)
'gal' => string '1' (length=1)
'type' => string 'image' (length=5)
'name' => string 'chalk_art_dies-irea_2nd_pic' (length=27)
'permalink' => string 'chalk-art-dies-irea-2nd-pic' (length=27)
'url' => string 'rxNsPoEiJboJQ32.jpg' (length=19)
'content' => string '' (length=0)
'date' => string '1432076359' (length=10)
'order' => string '20' (length=2)
'views' => string '0' (length=1)
1 =>
array (size=11)
'id' => string '10' (length=2)
'cat' => string '1' (length=1)
'gal' => string '1' (length=1)
'type' => string 'image' (length=5)
'name' => string '3dchalkart' (length=10)
'permalink' => string '3dchalkart' (length=10)
'url' => string 's57i5DKueUEI4lu.jpg' (length=19)
'content' => string '' (length=0)
'date' => string '1432076358' (length=10)
'order' => string '9' (length=1)
'views' => string '0' (length=1)
2 =>
current and next functions are deprecated for objects since PHP 8.1
Here is a way to do it using ArrayIterator
Keys
$list = new ArrayIterator(array('page1', 'page2', 'page3'));
$currentPage = 1;
$list->seek($currentPage);
echo $list->current(); // 'page2'
Values
$list = new ArrayIterator(array('page1', 'page2', 'page3'));
while ($list->current() !== 'page2') {
$list->next();
}
echo $list->current(); // 'page2'
Here's the complete #tjunglc 's approach with looping:
protected function getPrevNext($aArray,$key)
{
$aKeys = array_keys($aArray); //every element of aKeys is obviously unique
$aIndices = array_flip($aKeys); //so array can be flipped without risk
$i = $aIndices[$key]; //index of key in aKeys
if ($i > 0) $prev = $aArray[$aKeys[$i-1]]; //use previous key in aArray
if ($i < count($aKeys)-1) $next = $aArray[$aKeys[$i+1]]; //use next key in aArray
if (!isset($prev)) $prev = end($aArray);
if (!isset($next)) $next = reset($aArray);
return array($prev,$next);
}
Oh and thankx #tjunglc for this :)

Get key of a 3 dimensional array

Below is dump of how my array looks like. There is inner array called officers and I would want to loop through it and check if there is officer of a specific name and if so I would want to get the index key of the outer array.
'edges' =>
array (size=59)
0 =>
array (size=3)
'source' => int 0
'target' => int 12
'officers' =>
array (size=1)
0 => string 'PARKER, Thomas, Sir' (length=19)
1 =>
array (size=3)
'source' => int 0
'target' => int 19
'officers' =>
array (size=1)
0 => string 'STEVENS, Anne' (length=13)
So if I checked for STEVENS, Anne I would want to get key 1.
Here is code I found in a different question it works with 2d arrays but not with 3d array.
function array_search_inner ($array, $attr, $val, $strict = FALSE) {
// Error is input array is not an array
if (!is_array($array)) return FALSE;
// Loop the array
foreach ($array as $key => $inner) {
// Error if inner item is not an array (you may want to remove this line)
if (!is_array($inner)) return FALSE;
// Skip entries where search key is not present
if (!isset($inner[$attr])) continue;
if ($strict) {
// Strict typing
if ($inner[$attr] === $val) return $key;
} else {
// Loose typing
if ($inner[$attr] == $val) return $key;
}
}
// We didn't find it
return NULL;
}
Since there can be several index keys that fit the condition, it is reasonable to implement the function as a generator:
function getOfficerIndexKey($data, $officerName) {
foreach ($data['edges'] as $key => $value) {
in_array($officerName, $value['officers']) && (yield $key);
}
}
Now you can iterate over all found values:
foreach (getOfficerIndexKey($data, 'STEVENS, Anne') as $indexKey) {
// Do something
}
As well as just get the first found one:
getOfficerIndexKey($data, 'STEVENS, Anne')->current();

PHP array check all values is equal

array
0 =>
array
'point' => string '2'
1 =>
array
'point' => string '4'
2 =>
array
'point' => string '1'
I need checking values of 'point' in above array, if all values of 'point' is '4' it will return true as below array.
array
0 =>
array
'point' => string '4'
1 =>
array
'point' => string '4'
2 =>
array
'point' => string '4'
You just need to use 2 statements fomr PHP. if and for.
I used following script to test it (you can choose one of the loops(for or foreach))
$test = array(array('point' => 4), array('point' => 4));
function checkArrayForPointValue($array, $expectedValue)
{
$ok = true;
for ($i = 0; $i < count($array); $i++) {
if ($array[$i]['point'] != $expectedValue) {
$ok = false;
break;
}
}
// choose one of them
foreach ($array as $element) {
if ($element['point'] != $expectedValue) {
$ok = false;
break;
}
}
return $ok;
}
print(checkArrayForPointValue($test, '4') ? 'yay' : 'not yay');
Compare each value in a foreach :
function arrayComparePoint($array) {
$valueCompare = $array[0]['point'];
foreach ($array as $arrayPoint) {
foreach ($arrayPoint as $point) {
if ($valueCompare != $point) {
return false;
}
}
}
return true;
}
Simply use as
function checkArray($myArray) {
$result = array_unique(array_column($myArray, 'point'));
return (count($result) == 1 && $result[0] == '4') ? "true" : "false";
}
echo checkArray($myArray);

How to set an Arrays internal pointer to a specific position? PHP/XML

Im trying to build a little site using XML instead of a database.
I would like to build a next and prev button which will work relative to the content I have displayed.
I found the php function next() and prev() as well as current() but I do not know how to set the pointer to a specific position to be able to navigate relative to the current page.
$list=array('page1','page2','page3')
eg if im displaying contents of page2 how could I tell php i am at $list[1] so that next($list) shows page3?
Thanks in advance
If your array is always indexed consistently (eg. 'page1' is always at index '0'), it's fairly simple:
$List = array('page1', 'page2', 'page3', 'page4', 'page5');
$CurrentPage = 3; // 'page4'
while (key($List) !== $CurrentPage) next($List); // Advance until there's a match
I personally don't rely on automatic indexing because there's always a chance that the automatic index might change. You should consider explicitly defining the keys:
$List = array(
'1' => 'page1',
'2' => 'page2',
'3' => 'page3',
);
EDIT: If you want to test the values of the array (instead of the keys), use current():
while (current($List) !== $CurrentPage) next($List);
Using the functions below, you can get the next and previous values of the array.
If current value is not valid or it is the last (first - for prev) value in the array, then:
the function getNextVal(...) returns the first element value
the function getPrevVal(...) returns the last element value
The functions are cyclic.
function getNextVal(&$array, $curr_val)
{
$next = 0;
reset($array);
do
{
$tmp_val = current($array);
$res = next($array);
} while ( ($tmp_val != $curr_val) && $res );
if( $res )
{
$next = current($array);
}
return $next;
}
function getPrevVal(&$array, $curr_val)
{
end($array);
$prev = current($array);
do
{
$tmp_val = current($array);
$res = prev($array);
} while ( ($tmp_val != $curr_val) && $res );
if( $res )
{
$prev = current($array);
}
return $prev;
}
Using the functions below, you can get the next and previous KEYs of the array.
If current key is not valid or it is the last (first - for prev) key in the array, then:
the function getNext(...) returns 0 (the first element key)
the function getPrev(...) returns the key of the last array element
The functions are cyclic.
function getNext(&$array, $curr_key)
{
$next = 0;
reset($array);
do
{
$tmp_key = key($array);
$res = next($array);
} while ( ($tmp_key != $curr_key) && $res );
if( $res )
{
$next = key($array);
}
return $next;
}
function getPrev(&$array, $curr_key)
{
end($array);
$prev = key($array);
do
{
$tmp_key = key($array);
$res = prev($array);
} while ( ($tmp_key != $curr_key) && $res );
if( $res )
{
$prev = key($array);
}
return $prev;
}
The internal array pointer is mainly used for looping over an array within one PHP script. I wouldn't recommend using it for moving from page to page.
For that, just keep track of the page number and the page size (number of items per page). Then, when you're loading another page, you can use them to decide which array items to show. For example:
$pageNum = $_GET["pageNum"];
$pageSize = 10;
$startIndex = ($pageNum - 1) * $pageSize;
$endIndex = ($startIndex + $pageSize) - 1;
(or something similar)
another aproach without loops or search.
list($prev,$next) = getPrevNext($oObjects,$sCurrentKey);
function getPrevNext($aArray,$key){
$aKeys = array_keys($aArray); //every element of aKeys is obviously unique
$aIndices = array_flip($aKeys); //so array can be flipped without risk
$i = $aIndices[$key]; //index of key in aKeys
if ($i > 0) $prev = $aArray[$aKeys[$i-1]]; //use previous key in aArray
if ($i < count($aKeys)-1) $next = $aArray[$aKeys[$i+1]]; //use next key in aArray
return array($prev,$next);
}
I use this code for set internal pointer with key of array.
reset($List);
while (key($List) !== $id && key($List) !== null) next($List);
if(key($List) === null) end($List);
After that you can use prev() or next().
Update follow notice from #VaclavSir
Try this
public function getNextVal(&$array, $curr_val){
foreach($array as $k=>$v){
if($v['your_key'] == $curr_val){
if(isset($array[$k+1]))
return $array[$k+1];
else
return $array[0];
}
}
}
public function getPrevVal(&$array, $curr_val){
foreach($array as $k=>$v){
if($v['your_key'] == $curr_val){
if(isset($array[$k-1]))
return $array[$k-1];
else
return end($array);
}
}
}
for array like this:
array (size=3)
0 =>
array (size=11)
'id' => string '21' (length=2)
'cat' => string '1' (length=1)
'gal' => string '1' (length=1)
'type' => string 'image' (length=5)
'name' => string 'chalk_art_dies-irea_2nd_pic' (length=27)
'permalink' => string 'chalk-art-dies-irea-2nd-pic' (length=27)
'url' => string 'rxNsPoEiJboJQ32.jpg' (length=19)
'content' => string '' (length=0)
'date' => string '1432076359' (length=10)
'order' => string '20' (length=2)
'views' => string '0' (length=1)
1 =>
array (size=11)
'id' => string '10' (length=2)
'cat' => string '1' (length=1)
'gal' => string '1' (length=1)
'type' => string 'image' (length=5)
'name' => string '3dchalkart' (length=10)
'permalink' => string '3dchalkart' (length=10)
'url' => string 's57i5DKueUEI4lu.jpg' (length=19)
'content' => string '' (length=0)
'date' => string '1432076358' (length=10)
'order' => string '9' (length=1)
'views' => string '0' (length=1)
2 =>
current and next functions are deprecated for objects since PHP 8.1
Here is a way to do it using ArrayIterator
Keys
$list = new ArrayIterator(array('page1', 'page2', 'page3'));
$currentPage = 1;
$list->seek($currentPage);
echo $list->current(); // 'page2'
Values
$list = new ArrayIterator(array('page1', 'page2', 'page3'));
while ($list->current() !== 'page2') {
$list->next();
}
echo $list->current(); // 'page2'
Here's the complete #tjunglc 's approach with looping:
protected function getPrevNext($aArray,$key)
{
$aKeys = array_keys($aArray); //every element of aKeys is obviously unique
$aIndices = array_flip($aKeys); //so array can be flipped without risk
$i = $aIndices[$key]; //index of key in aKeys
if ($i > 0) $prev = $aArray[$aKeys[$i-1]]; //use previous key in aArray
if ($i < count($aKeys)-1) $next = $aArray[$aKeys[$i+1]]; //use next key in aArray
if (!isset($prev)) $prev = end($aArray);
if (!isset($next)) $next = reset($aArray);
return array($prev,$next);
}
Oh and thankx #tjunglc for this :)

Categories