PHP: find key position in multidimensional array [duplicate] - php

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
PHP: get keys of independent arrays
Hello.
I have a multi-dimensional array. I want a function that finds the position of the given array key (all my array keys are strings) and then returns the position of the key as an array.
E.g:
$arr = array
(
'fruit' => array(
'apples' => array(),
'oranges' => array(),
'bananas' => array()
),
'vegetables' => array(
'tomatoes' => array(),
'carrots' => array(),
'celery' => array(),
'beets' => array
(
'bears' => array(),
'battlestar-galactica' => array()
),
),
'meat' => array(),
'other' => array()
);
Now if I call the function like this:
theFunction('bears');
It should return:
array(1, 3, 0);

function array_tree_search_key($a, $subkey) {
foreach (array_keys($a) as $i=>$k) {
if ($k == $subkey) {
return array($i);
}
elseif ($pos = array_tree_search_key($a[$k], $subkey)) {
return array_merge(array($i), $pos);
}
}
}

Related

PHP sort multidimensional array by array list priority [duplicate]

This question already has answers here:
Sorting a php array of arrays by custom order
(8 answers)
Closed 28 days ago.
I have array $data containing data about animals. I would like to sort this array by child element:
source array ($data):
Array (
[0] => (
'name' => 'Leo'
'type' => 'cat'
)
[1] => (
'name' => 'Max'
'type' => 'dog'
)
[2] => (
'name' => 'Elsa'
'type' => 'fish'
)
...
)
priority array ($priority)
$priority = [
'fish', 'dog', 'cat',
];
I would like to sort source array using priority array. I tried:
sort($data, function (int $item1, int $item2) use($priority) {
foreach($priority as $key => $value) {
if($item1 == $value)
{
return 0;
break;
}
if($item2 == $value)
{
return 1;
break;
}
}
return 0;
});
You can use usort with a custom compare function, like so:
<?php
$arr = array(
0 => array(
'name' => 'Leo',
'type' => 'cat'
),
1 => array(
'name' => 'Max',
'type' => 'dog'
),
2 => array(
'name' => 'Elsa',
'type' => 'fish'
)
);
$priority = array('fish', 'dog', 'cat');
usort($arr, function($a, $b) use($priority) {
return array_search($a['type'], $priority) <=> array_search($b['type'], $priority);
});
var_dump($arr);
How this works:
usort accepts a custom compare function, you can pass it the priority array, then use the spaceship operator to compare the value indexes in priority.
Try it out: http://sandbox.onlinephpfunctions.com/code/03fdfa61b1bd8b0b84e5f08ab11b6bc90eeaef4a

how to get multi-dimensional array data with another one-dimension array

What I'd like to do is have a function that accepts two arguments, both arrays, the first being a one-dimensional array of varying lengths and the second is a multi-dimensional array of varying depths and lengths. The first array is never associative, the second is always a fully associative array.
This function would return the requested value from the multi-dimensional array as indicated by the first array.
Assume that the first array will always be hand-written and passed to this function. Meaning the developer always knows there is a value to be returned from the multi-dimensional array and would never pass a request to the function where a value did not exist.
I think the code below is the best example at what I'm trying to achieve.
//Example multi-dimensional array
$multi = array(
'fruit' => array(
'red' => array(
'strawberries' => '$2.99/lb',
'apples' => '$1.99/lb'
),
'green' => array(
'honeydew' => '$3.39/lb',
'limes' => '$0.75/lb'
)
),
'vegetables' => array(
'yellow' => array(
'squash' => '$1.29/lb',
'bellpepper' => '$0.99/lb'
),
'purple' => array(
'eggplant' => '$2.39/lb'
)
),
'weeklypromo' => '15% off',
'subscribers' => array(
'user1#email.com' => 'User 1',
'user2#email.com' => 'User 2',
'user3#email.com' => 'User 3',
'user4#email.com' => 'User 4'
)
);
//Example one-dimensional array
$single = array('fruit', 'red', 'apples');
function magicfunc($single, $multi) {
//some magic here that looks something like below
$magic_value = $multi[$single[0]][$single[1]][$single[2]];
return $magic_value;
}
//Examples:
print magicfunc(array('fruit', 'red', 'apples'), $multi);
Output:
$1.99/lb
print magicfunc(array('subscribers', 'user3#email.com'), $multi);
Output:
User 3
print magicfunc(array('weeklypromo'), $multi);
Output:
15% off
This returns the values as requested:
function magicfunc($single, $multi) {
while (true) {
if (!$single) {
break;
}
$searchIndex = array_shift($single);
foreach ($multi as $k => $val) {
if ($k == $searchIndex) {
$multi = $val;
continue 2;
}
}
}
return $multi;
}

Get key of multidimensional array?

For example, I have multidimensional array as below:
$array = array (
0 =>
array (
'id' => '9',
'gallery_id' => '2',
'picture' => '56475832.jpg'
),
1 =>
array (
'id' => '8',
'gallery_id' => '2',
'picture' => '20083622.jpg'
),
2 =>
array (
'id' => '7',
'gallery_id' => '2',
'picture' => '89001465.jpg'
),
3 =>
array (
'id' => '6',
'gallery_id' => '2',
'picture' => '47360232.jpg'
),
4 =>
array (
'id' => '5',
'gallery_id' => '2',
'picture' => '4876713.jpg'
),
5 =>
array (
'id' => '4',
'gallery_id' => '2',
'picture' => '5447392.jpg'
),
6 =>
array (
'id' => '3',
'gallery_id' => '2',
'picture' => '95117187.jpg'
)
);
How can I get key of array(0,1,2,3,4,5,6)?
I have tried a lot of examples, but nothing has worked for me.
This is quite simple, you just need to use array_keys():
$keys = array_keys($array);
See it working
EDIT For your search task, this function should do the job:
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;
}
// Example usage
$key = array_search_inner($array, 'id', 9);
The fourth parameter $strict, if TRUE, will use strict type comparisons. So 9 will not work, you would have to pass '9', since the values are stored as strings. Returns the key of the first occurence of a match, NULL if the value is not found, or FALSE on error. make sure to use a strict comparison on the return value, since 0, NULL and FALSE are all possible return values and they will all evaluate to 0 if using loose integer comparisons.
Try this , I think it will help you.
foreach ($array as $key=>$value)
{
echo $key.'<br/>';
echo $value['id'].'<br/>';
echo $value['gallery_id'].'<br/>';
echo $value['picture'].'<br/><br/>';
}
sometimes it is to easy to find ;)
array_keys($array);
array_keys
Probably http://php.net/manual/en/function.array-keys.php ?
Convert your double dimensional array on your own:
$tmp = null
foreach($array as $key => $value) {
$tmp[] = $key;
}
print_r($tmp);
You mean something like this:
function getKeys($array)
{
$resultArr = array();
foreach($array as $subArr) {
$resultArr = array_merge($resultArr, $subArr);
}
return array_keys($resultArr);
}

Check the 'form' of a multidimensional array for validation [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
recursive array_diff()?
I have a static multidimensional array which is always going to be in the same form. E.g. it will have the same keys & hierarchy.
I want to check a posted array to be in the same 'form' as this static array and if not error.
I have been trying various methods but they all seem to end up with a lot of if...else components and are rather messy.
Is there a succinct way to achieve this?
In response to an answer from dfsq:
$etalon = array(
'name' => array(),
'income' => array(
'day' => '',
'month' => array(),
'year' => array()
),
'message' => array(),
);
$test = array(
'name' => array(),
'income' => array(
'day' => '',
'month' => array(),
'year' => array()
),
'message' => array(),
);
// Tests
$diff = array_diff_key_recursive($etalon, $test);
var_dump(empty($diff));
print_r($diff);
And the results from that are
bool(false)
Array ( [name] => 1 [income] => Array ( [month] => 1 [year] => 1 ) [message] => 1 )
Author needs a solution which would test if the structure of the arrays are the same. Next function will make a job.
/**
* $a1 array your static array.
* $a2 array array you want to test.
* #return array difference between arrays. empty result means $a1 and $a2 has the same structure.
*/
function array_diff_key_recursive($a1, $a2)
{
$r = array();
foreach ($a1 as $k => $v)
{
if (is_array($v))
{
if (!isset($a2[$k]) || !is_array($a2[$k]))
{
$r[$k] = $a1[$k];
}
else
{
if ($diff = array_diff_key_recursive($a1[$k], $a2[$k]))
{
$r[$k] = $diff;
}
}
}
else
{
if (!isset($a2[$k]) || is_array($a2[$k]))
{
$r[$k] = $v;
}
}
}
return $r;
}
And test it:
$etalon = array(
'name' => '',
'income' => array(
'day' => '',
'month' => array(),
'year' => array()
),
'message' => ''
);
$test = array(
'name' => 'Tomas Brook',
'income' => array(
'day' => 123,
'month' => 123,
'year' => array()
)
);
// Tests
$diff = array_diff_key_recursive($etalon, $test);
var_dump(empty($diff));
print_r($diff);
This will output:
bool(false)
Array
(
[income] => Array
(
[month] => Array()
)
[message] =>
)
So checking for emptiness of $diff array will tell you if arrays have the same structure.
Note: if you need you can also test it in other direction to see if test array has some extra keys which are not present in original static array.
You could user array_intersect_key() to check if they both contain the same keys. If so, the resulting array from that function will contain the same values as array_keys() on the source array.
AFAIK those functions aren't recursive, so you'd have to write a recursion wrapper around them.
See User-Notes on http://php.net/array_diff_key
Are you searching for the array_diff or array_diff_assoc functions?
use foreach with the ifs...if u have different tests for the different inner keys eg
$many_entries = ("entry1" = array("name"=>"obi", "height"=>10));
and so on, first define functions to check the different keys
then a foreach statement like this
foreach($many_entries as $entry)
{
foreach($entry as $key => $val)
{
switch($key)
{
case "name": //name function
//and so on
}
}
}

PHP: get keys of independent arrays

I have two arrays.
Example of the first array:
$arrayOne = array
(
'fruit' => array(
'apples' => array(),
'oranges' => array(),
'bananas' => array()
),
'vegetables' => array(
'tomatoes' => array(),
'carrots' => array(),
'celery' => array(),
'beets' => array
(
'bears' => array(),
'battlestar-galactica' => array()
),
),
'meat' => array(),
'other' => array()
);
2nd:
$arrayTwo = array
(
'frewt' => array(
'aplz' => array(),
'orangeez' => array(),
'bunanahs' => array()
),
'vetchteblz' => array(
'toem8ohs' => array(),
'careodds' => array(),
'sell-R-e' => array(),
'beats' => array
(
'bare z' => array(),
'tablestar-neglectia' => array()
),
),
'neat' => array(),
'mother' => array()
);
Notice that the two arrays are in the exact same "format" (same number of dimensions, number of keys, order, etc., etc.), only the names of the keys differ. (The array keys basically hold all the data.)
I have a few variables that address the keys of the first array ($arrayOne). E.g. $one would address the first dimension of the first array, so it's value (string) would be one out of 'fruit', 'vegetables', 'meat' or 'other'.
$two would be 'apples' or 'oranges' or 'bananas' or 'tomatoes' or 'carrots', etc., you get the idea. (There's vars for each dimension)
As I said, those variables only address $arrayOne. I want to be able to address the keys in the second array too, though. Meaning, by looking at the value of $one I want to be able to get the array_key of both arrays.
$arrayOne = //...
$arrayTwo = //...
function getPosition(array $arr, $key) {
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr),
RecursiveIteratorIterator::SELF_FIRST);
$pos = array();
foreach ($it as $k => $v) {
if (count($pos) - 1 > $it->getDepth()) {
array_pop($pos);
$pos[$it->getDepth()]++;
}
elseif (count($pos) - 1 < $it->getDepth()) {
array_push($pos, 0);
}
else {
$pos[$it->getDepth()]++;
}
if ($k === $key) {
return $pos;
}
}
}
function getElementKey(array $arr, array $position) {
$cur = $arr;
$curkey = null;
foreach ($position as $p) {
reset($cur);
for ($i = 0; $i < $p; $i++) {
next($cur);
}
$curkey = key($cur);
$cur = current($cur);
}
return $curkey;
}
var_dump(getPosition($arrayOne, "battlestar-galactica"));
var_dump(getElementKey($arrayTwo, array(1, 3, 1)));
gives:
array(3) {
[0]=>
int(1)
[1]=>
int(3)
[2]=>
int(1)
}
string(19) "tablestar-neglectia"
You can feed the result of getPosition to getElementKey:
getElementKey($arrayTwo, getPosition($arrayOne, "battlestar-galactica"));
Check out array_keys from both arrays and then map the positions. Like array_keys for your arrays will give you -
$arrayKeyOne = array('fruit', 'vegetables', 'meat', 'other');
$arrayKeyTwo = array('frewt', 'vetchteblz', 'meat', 'mother');
Then a $arrayKeyTwo[array_search($one, $arrayKeyOne)] shuld give you what you want. Let know if this helps.

Categories