How to get hierarchy path of an element in an Array - php

I always want to get the exact path of an element in an array.
Example array:
array(a=>'aaa', 'b'=> array ('bbb1', 'bbb2' => array('bbb3', 'bbb4')));
So, for reaching to 'bbb4', I need to go through (b => bbb2 => bbb4).
How to get this path in multidimensional array?

function get_from_array($toBeSearchedArray , $searchValue , &$exactPath)
{
foreach($toBeSearchedArray as $key=>$value)
{
if(is_array($value) && count($value) > 0)
{
$found = get_from_array($value , $searchValue , $exactPath);
if($found)
{
$exactPath = $key."=>".$exactPath;
return TRUE;
}
}
if($value == $searchValue)
{
$exactPath = $value;
return true;
}
}
return false;
}
$exactPath = "";
$argArray = array('a'=>'aaa', 'b'=> array ('bbb1', 'bbb2' => array('bbb3', 'bbb4')));
get_from_array($argArray , "bbb4" , $exactPath);
echo $exactPath;

Related

Check if a value exists multidimensional array and return its key

I have an array, say
$updates = array();
$updates['U1'] = array('F1', 'F2', 'F5');
$updates['U2'] = array('F3');
$updates['U3'] = array('F3', 'F4');
I need search for a value say F5 so it should return the key U1.
And also if there is multiple occurrence of a value, should return the last key.
Eg. searching F3 should return U3 and not U2.
I have searched a lot and can't find a way. I am looking for a solution without using loops.
without using loop:
function findArrVal($arr = [], $param){
static $indx = 0;
if($indx == 0){
krsort($arr);
}
$keys = array_keys($arr);
$values = array_values($arr);
if( count($values) == $indx ){
return false;
} else if( is_array($values[$indx]) && in_array($param, $values[$indx])){
return $keys[$indx];
} else {
++$indx;
return findArrVal($arr, $param);
}
return FALSE;
}
using loop:
function findArrVal($arr = [], $param){
krsort($arr);
foreach($arr as $key => $ar){
if(is_array($ar) && in_array($param, $ar)){
return $key;
}
}
return FALSE;
}
findArrVal($updates,'F3');
krsort - sorts the array in reverse order. ( to find the value at first occurrence )
is_array to check if the child value is an array type.
in_array to find the item on the child array.
Maybe It's helpful for you.
function _getFindArrayKey(array $arr, $key)
{
if (array_key_exists($key, $arr)) {
return true;
}
// check arrays contained in this array
foreach ($arr as $element) {
if (is_array($element)) {
if (_getFindArrayKey($element, $key)) {
return true;
}
}
}
return false;
}

Search inside multidimensional array and return other key value

I have the following
Multidimensional array.
What I'm trying to do is to search for an IDITEM value and if it's found, return the value of the "PRECO" key.
I'm using the following function to check if the value exists and it works fine, but I can't find a way to get the "PRECO" value of the found IDITEM.
Function:
function search_array($needle, $haystack) {
if(in_array($needle, $haystack)) {
return true;
}
foreach($haystack as $element) {
if(is_array($element) && search_array($needle, $element))
return true;
}
return false;
}
Anyone can help me with that?
You can change the first if statement to return it instead of returning a boolean :
function search_array($needle, $haystack) {
if(in_array($needle, $haystack) && array_key_exists('PRECO', $haystack)) {
return $haystack['PRECO'];
}
foreach($haystack as $element) {
if(is_array($element))
{
$result = search_array($needle, $element);
if($result !== false)
return $result;
}
}
return false;
}
The easiest idea I can remember is converting that boolean search_array into a path creator, where it will return the path for the item, or false if it isn't found.
function get_array_path_to_needle($needle, array $haystack)
{
if(in_array($needle, $haystack))
{
return true;
}
foreach($haystack as $key => $element)
{
if(is_array($element) && ($path = get_array_path_to_needle($needle, $element)) !== false)
{
return $path === true ? $key : $key . '.' . $path;
}
}
return false;
}
Then, since you already have the path, then rerun the array to fetch the item
function get_array_value_from_path(array $path, array $haystack)
{
$current = $haystack;
foreach($path as $key)
{
if(is_array($current) && array_key_exists($key, $current))
{
$current = $current[$key];
}
else
{
return false;
}
}
return $current;
}
This wont get you the PRECO, but it will return the item (array) where id found the value you searched for.
So a simple usage would be:
$path = get_array_path_to_needle('000000000000001650', $data);
$item = get_array_value_from_path(explode('.', $path), $data);
// here you have full array for that item found
print_r($item);
// here you have your price
print_r($item['PRECO']);
Use a static variable to remember the status between multiple function calls, and also to store the desired PRECO value. It makes the function remember the value of the given variable ($needle_value in this example) between multiple calls.
So your search_array() function should be like this:
function search_array($needle, $haystack){
static $needle_value = null;
if($needle_value != null){
return $needle_value;
}
foreach($haystack as $key => $value){
if(is_array($value)){
search_array($needle, $value);
}else if($needle == $value){
$needle_value = $haystack['PRECO'];
break;
}
}
return $needle_value;
}
This function will finally return $needle_value, which is your desired PRECO value from the haystack.
The simplest way is to use a foreach loop twice. Check for the key and store the result into an array for later use.
Based on your array, the below
$search = '000000000000001650';
foreach($array as $element){
foreach ($element['ITEM'] as $item){
if (isset($item['IDITEM']) and $item['IDITEM'] == $search){
$results[] = $item['PRECO'];
}
}
}
print_r($results);
Will output
Array
(
[0] => 375
)
Here is the simple example with array:
// your array with two indexes
$yourArr = array(
0=>array(
'IDDEPARTAMENTO'=>'0000000001',
'DESCRDEPT'=>'Área',
'ITEM'=>
array(
array(
'SETID'=>'RX',
'IDITEM'=>'000000000000001367',
'DESCRITEM'=>'PISTA TESTE DRIV',
'PRECO'=>'1338.78'),
array(
'SETID'=>'RX',
'IDITEM'=>'000000000000001925',
'DESCRITEM'=>'PISTA TESTE DRIV2',
'PRECO'=>'916'),
)
),
1=>array(
'IDDEPARTAMENTO'=>'0000000010',
'DESCRDEPT'=>'Merch',
'ITEM'=>
array(
array(
'SETID'=>'RX',
'IDITEM'=>'000000000000002036',
'DESCRITEM'=>'PISTA TESTE DRIV23',
'PRECO'=>'200.78'),
array(
'SETID'=>'RX',
'IDITEM'=>'000000000000001608',
'DESCRITEM'=>'PISTA CRACHÁ DRIV4',
'PRECO'=>'44341'),
)
));
// solution
$newArr = array();
foreach ($yourArr as $value) {
foreach ($value as $key => $innerVal) {
if($key == 'ITEM'){
foreach ($innerVal as $key_inner => $keyinner) {
if(!empty($keyinner['IDITEM'])){
$newArr[$keyinner['IDITEM']] = $keyinner['PRECO'];
}
}
}
}
}
echo "<pre>";
print_r($newArr);
Result values with IDITEM:
Array
(
[000000000000001367] => 1338.78
[000000000000001925] => 916
[000000000000002036] => 200.78
[000000000000001608] => 44341
)

unset inside eval not working

I'm trying to remove an item from an array based on string;
public function delete($path){
// a key path given
if(strpos($path, '.') !== false){
$parts = explode('.', $path);
$first_key = array_shift($parts);
$data = $this->get($path);
// first key doesn't exist
if($data === false)
return false;
$parts = implode('"]["', $parts);
if(eval('if(isset($data["'.$parts.'"])){ unset($data["'.$parts.'"]); return true; } return false;'))
return $this->set($first_key, $data);
}
// a single key given
if(isset($this->data[$path]){
unset($this->data[$path]);
return true;
}
return false;
}
And it only works for single keys. Apparently the eval doesn't modify $data for some reason.
delete('test') works, but delete('test.child') doesn't...
I don't see why you'd need eval() here. See the following to replace your eval() construct:
<?php
function removeFromArray(&$array, $path)
{
if (!is_array($path)) {
$path = explode('.', trim($path, '.'));
}
$current = &$array;
while ($path) {
$key = array_shift($path);
// isset() would fail on `$array[$key] === null`
if (!array_key_exists($key, $current)) {
// abort if the array element does not exist
return false;
}
if (!$path) {
// reached the last element
unset($current[$key]);
return true;
}
if (!is_array($current[$key])) {
// can't go deeper, so abort
return false;
}
// continue with next deeper element
$current = &$current[$key];
}
return false;
}
$data = array(
'a' => 1,
'b' => array(
'c' => 2,
'd' => 3,
'e' => array(
'f' => 4,
),
),
);
var_dump(
removeFromArray($data, 'b.e.f'),
$data,
removeFromArray($data, 'b.c'),
$data
);
function unset_multiple($arr = [], $keys = [], $limitKeys = 30){
if($keys && count($keys) <= $limitKeys && is_array($arr) && count($arr) > 0){
foreach($keys as $key){
$keys[$key] = null;
}
return array_diff_key($arr, $keys);
} else{
throw new Exception("Input array is invalid format or number of keys to remove too large");
}
}
Example called:
$arr = array("name" => "Vuong", "age" => 20, "address" => "Saigon");
$res = unset_multiple($arr, ["name", "age"]);
//Result: ["address" => "Saigon"]
Make sure $keys param has all available keys in $arr param (only two-dimensional arrays). Need to remember this function is a helper to quickly removing multiple elements of array, not a function returns the absolute accurate results for all cases.

best way to check a empty array?

How can I check an array recursively for empty content like this example:
Array
(
[product_data] => Array
(
[0] => Array
(
[title] =>
[description] =>
[price] =>
)
)
[product_data] => Array
(
[1] => Array
(
[title] =>
[description] =>
[price] =>
)
)
)
The array is not empty but there is no content. How can I check this with a simple function?
Thank!!
function is_array_empty($InputVariable)
{
$Result = true;
if (is_array($InputVariable) && count($InputVariable) > 0)
{
foreach ($InputVariable as $Value)
{
$Result = $Result && is_array_empty($Value);
}
}
else
{
$Result = empty($InputVariable);
}
return $Result;
}
If your array is only one level deep you can also do:
if (strlen(implode('', $array)) == 0)
Works in most cases :)
Solution with array_walk_recursive:
function empty_recursive($value)
{
if (is_array($value)) {
$empty = TRUE;
array_walk_recursive($value, function($item) use (&$empty) {
$empty = $empty && empty($item);
});
} else {
$empty = empty($value);
}
return $empty;
}
Assuming the array will always contain the same type of data:
function TestNotEmpty($arr) {
foreach($arr as $item)
if(isset($item->title) || isset($item->descrtiption || isset($item->price))
return true;
return false;
}
Short circuiting included.
function hasValues($input, $deepCheck = true) {
foreach($input as $value) {
if(is_array($value) && $deepCheck) {
if($this->hasValues($value, $deepCheck))
return true;
}
elseif(!empty($value) && !is_array($value))
return true;
}
return false;
}
Here's my version. Once it finds a non-empty string in an array, it stops. Plus it properly checks on empty strings, so that a 0 (zero) is not considered an empty string (which would be if you used empty() function). By the way even using this function just for strings has proven invaluable over the years.
function isEmpty($stringOrArray) {
if(is_array($stringOrArray)) {
foreach($stringOrArray as $value) {
if(!isEmpty($value)) {
return false;
}
}
return true;
}
return !strlen($stringOrArray); // this properly checks on empty string ('')
}
If anyone stumbles on this question and needs to check if the entire array is NULL, meaning that each pair in the array is equal to null, this is a handy function. You could very easily modify it to return true if any variable returns NULL as well. I needed this for a certain web form where it updated users data and it was possible for it to come through completely blank, therefor not needing to do any SQL.
$test_ary = array("1"=>NULL, "2"=>NULL, "3"=>NULL);
function array_empty($ary, $full_null=false){
$null_count = 0;
$ary_count = count($ary);
foreach($ary as $value){
if($value == NULL){
$null_count++;
}
}
if($full_null == true){
if($null_count == $ary_count){
return true;
}else{
return false;
}
}else{
if($null_count > 0){
return true;
}else{
return false;
}
}
}
$test = array_empty($test_ary, $full_null=true);
echo $test;
$arr=array_unique(array_values($args));
if(empty($arr[0]) && count($arr)==1){
echo "empty array";
}
Returns TRUE if passed a variable other than an array, or if any of the nested arrays contains a value (including falsy values!). Returns FALSE otherwise.
Short circuits.
function has_values($var) {
if (is_array($var)) {
if (empty($var)) return FALSE;
foreach ($var as $val) {
if(has_values($val)) return TRUE;
}
return FALSE;
}
return TRUE;
}
Here's a good utility function that will return true (1) if the array is empty, or false (0) if not:
function is_array_empty( $mixed ) {
if ( is_array($mixed) ) {
foreach ($mixed as $value) {
if ( ! is_array_empty($value) ) {
return false;
}
}
} elseif ( ! empty($mixed) ) {
return false;
}
return true;
}
For example, given a multidimensional array:
$products = array(
'product_data' => array(
0 => array(
'title' => '',
'description' => null,
'price' => '',
),
),
);
You'll get a true value returned from is_array_empty(), since there are no values set:
var_dump( is_array_empty($products) );
View this code interactively at: http://codepad.org/l2C0Efab
I needed a function to filter an array recursively for non empty values.
Here is my recursive function:
function filterArray(array $array, bool $keepNonArrayValues = false): array {
$result = [];
foreach ($array as $key => $value) {
if (is_array($value)) {
$value = $this->filterArray($value, $keepNonArrayValues);
}
// keep non empty values anyway
// otherwise only if it is not an array and flag $keepNonArrayValues is TRUE
if (!empty($value) || (!is_array($value) && $keepNonArrayValues)) {
$result[$key] = $value;
}
}
return array_slice($result, 0)
}
With parameter $keepNonArrayValues you can decide if values such 0 (number zero), '' (empty string) or false (bool FALSE) shout be kept in the array. In other words: if $keepNonArrayValues = true only empty arrays will be removed from target array.
array_slice($result, 0) has the effect that numeric indices will be rearranged (0..length-1).
Additionally, after filtering the array by this function it can be tested with empty($filterredArray).

How to check if a certain part of the array exists in another array?

I have an two associative arrayes and I want to check if
$array1["foo"]["bar"]["baz"] exists in $array2["foo"]["bar"]["baz"]
The values doesn't matter, just the "path".
Does array_ intersect_ assoc do what I need?
If not how can I write one myself?
Try this:
<?php
function array_path_exists(&$array, $path, $separator = '/')
{
$a =& $array;
$paths = explode($separator, $path);
$i = 0;
foreach ($paths as $p) {
if (isset($a[$p])) {
if ($i == count($paths) - 1) {
return TRUE;
}
elseif(is_array($a[$p])) {
$a =& $a[$p];
}
else {
return FALSE;
}
}
else {
return FALSE;
}
$i++;
}
}
// Test
$test = array(
'foo' => array(
'bar' => array(
'baz' => 1
)
),
'bar' => 1
);
echo array_path_exists($test, 'foo/bar/baz');
?>
If you only need to check if the keys exist you could use a simple if statement.
<?php
if (isset($array1["foo"]["bar"]["baz"]) && isset($array2["foo"]["bar"]["baz"]
)) {
//exists
}

Categories