Retrieve multiple array values with extract
Solution 1
$arr = array(
array(
'index1'=>'something',
'index2'=>'something else',
'index3'=>'something more',
),
array(
'index1'=>'something',
'index2'=>'something else',
'index3'=>'something more',
),
array(
'index1'=>'something',
'index2'=>'something else',
'index3'=>'something more',
)
);
$output = Set::classicExtract($arr, '{n}.{index[1-2]}');
print_r($output);
// output
Array
(
[0] => Array
(
[index1] => something
[index2] => something else
)
[1] => Array
(
[index1] => something
[index2] => something else
)
[2] => Array
(
[index1] => something
[index2] => something else
)
)
Solution 2
One way (if you only want to keep a few results):
Hash::merge(
Hash::extract($array, '{n}.index1'),
Hash::extract($array, '{n}.index2')
);
Another way (if you only want to remove a few):
Hash::remove($array, '{n}.index3');
Solution 3
Set is AWESOME! You can't do this directly with Set::extract, but you CAN build an associative array of the the two array indexes using Set::combine:
Set::combine($myArray, '{n}.index1', '{n}.index2')
A working example looks like this:
$myArray = array(
array('index1'=>'something 1', 'index2'=>'something else 1', 'index3'=>'something more 1'),
array('index1'=>'something 2', 'index2'=>'something else 2', 'index3'=>'something more 2'),
array('index1'=>'something 3', 'index2'=>'something else 3', 'index3'=>'something more 3'),
);
debug(Set::combine($myArray, '{n}.index1', '{n}.index2'));
This will take an array like you mentioned:
array(
[0]=>
[index1]=>something 1
[index2]=>something else 1
[index3]=>something more 1
[1]=>
[index1]=>something 2
[index2]=>something else 2
[index3]=>something more 2
[2]=>
[index1]=>something 3
[index2]=>something else 3
[index3]=>something more 3
)
and turn it into this:
Array (
[something1] => something else 1
[something2] => something else 2
[something3] => something else 3
)
Solution 4
Have you tried Set::extract($array, '{n}.{s}'); ?
EDIT: If your array dimension is exactly like the one in your answer, you could try array_keys(Set::extract($array, '{n}.{s}'));
Solution 5
I am not sure why you want to stick with the Set
class ? If it doesn't suit your need, why would you absolutely use it and not create your own function ?
You say in one of your comments that you want to avoid foreach
loops. But the Set
class methods are full of foreach
loops themselve. I may miss the point...
Personnaly I would do it simply with a function like this one:
function filter_fields($array_to_filter, $fields_to_keep)
{
foreach($array_to_filter as $i => $sub_array)
{
foreach($sub_array as $field => $value)
{
if(!in_array($field, $fields_to_keep))
{
unset($array_to_filter[$i][$field]);
}
}
}
return $array_to_filter;
}
Here is an example of what it would return:
print_r($array_to_filter);
/*
Array
(
[0] => Array
(
[index1] => abc
[index2] => def
[index3] => ghi
)
[1] => Array
(
[index1] => jkl
[index2] => mno
[index3] => poq
)
)
*/
$filtered_array = filter_fields($array_to_filter, array('index1', 'index3'));
print_r($filtered_array);
/*
Array
(
[0] => Array
(
[index1] => abc
[index3] => ghi
)
[1] => Array
(
[index1] => jkl
[index3] => poq
)
)
*/
Related videos on Youtube
Tim Joyce
I am a developer for php, html, css, javascript, jquery, and a few others. These are just the fun ones for me.
Updated on September 16, 2022Comments
-
Tim Joyce over 1 year
array( [0]=> [index1]=>something [index2]=>something else [index3]=>something more [1]=> [index1]=>something [index2]=>something else [index3]=>something more [2]=> [index1]=>something [index2]=>something else [index3]=>something more )
EDIT: So I would like to retrieve the following:
array( [0]=> [index1]=>something [index2]=>something else [1]=> [index1]=>something [index2]=>something else [2]=> [index1]=>something [index2]=>something else )
How do I get multiple indexes of the array using the Set::extract function in cakephp?
This retrieves one value:
Set::extract($array, '{n}.index1');
but I would like to get multiple values ... say, index1 and index2.
I tried statements like the following, to no avail.
Set::extract($array, '[{n}.index1, {n}.index2']);
EDIT
$__pages = Hash::merge( Hash::extract($pages, 'pages.{n}.id'), Hash::extract($pages, 'pages.{n}.title') ); pr($__pages);
Output:
Array ( [0] => 2 [1] => 4 [2] => 104 [3] => Sample Page [4] => about us [5] => Services )
That doesn't really help me since I still need the association like so:
Array( [2] => Sample Page [4] => About us [104] => Services )
I would even be happy with :
Array( Array(id => 2, title => Sample Page) Array(id => 4, title => About Us) Array(id => 104, title => Services) )
ANSWER thecodeparadox's answer works for the test code that I provided. Here is the real life code in case someone stumbles here. In the book it states, "any string literal enclosed in brackets besides {n} and {s}) is interpreted as a regular expression." This line seemed to be hidden and not very blatant. So knowing this, I simply used regex rules to retrieve the data I needed. I have an array that pulled wordpress posts from an api, I needed to narrow down the results to
id, title
.array( posts=> 0=> id => 3 slug => sample-page type => page title => Sample Page //...and so on 1=> id => 7 slug => sample-page-2 type => page title => Sample Page 2 //...and so on
To retrieve just the id and title I added the following line.
pr(Set::classicExtract($pages, 'pages.{n}.{(id|title)}'));
this gave me:
array( posts=> 0=> id => 3 title => Sample Page 1=> id => 7 title => Sample Page 2
DOCUMENTATION: Book
-
Tim Joyce over 11 yearsThis will return all strings in the array.
-
Tim Joyce over 11 yearsI see what you are saying. I should reword the question, I need the values to come along with the keys.
-
Marius over 11 yearsI think I'm missing something here... Assuming you have this array: $array = array(array('index1'=>'something', 'index2'=>'something else', 'index3'=>'something more'), array('index1'=>'something', 'index2'=>'something else', 'index3'=>'something more')); then accesing the keys and values from the subarray is as easy as getting $array[index], no?
-
Tim Joyce over 11 yearsI simplified the array. The array could have potentially hundreds of nested arrays with the same keys. Trying to avoid a foreach loop.
-
Marius over 11 yearsI understand, but the question is: the keys from the second level array can repeat? like in my example above, where you have index1, index2 and index 3 in the second subarray, too? In this case what exactly do you want to get in the result? You should put an initial array with 2 or 3 subarrays and then an example array to specify the format of the array you want to get as a result
-
dogmatic69 over 11 years@TimJoyce you can not 'avoid a foreach', that is what Hash::* uses. Somewhere there will be a loop.
-
Tim Joyce over 11 yearsI like your first approach here, and I think it's close. I updated my question to provide you with the output I got when doing that. The formatting is just a bit off because I still need the id and title to be an association. Thanks
-
Tim Joyce over 11 yearsThank you for your answer. When I said I wanted to avoid a foreach loop, it's because I already know how to do it that way. I was looking for a more "Cake" way of doing this. I feel the new cakephp documentation for 2.x is lacking in many ways and hoping someone has the answer. Since my migration to 2.x I have google searched most of my problems because of the lack of documentation. The api is great but the cookbook is not.
-
nIcO over 11 yearsI believe you that you know how to do it yourself :-) But if the Cake libraries can't, that is yet another reason to create your own function.
-
dogmatic69 over 11 yearsThis can all be done in a single line, $filtered = Hash::remove($array, '{n}.index3');
-
nIcO over 11 yearsIf we want to discard only one field, that's true. But with many more fields Hash::remove() would have to be called many times, which would be less performent.
-
thecodeparadox over 11 years@Tim Joyce Please test my answer.. and I hope you'll get your desired answer. Thanks.
-
Tim Joyce over 11 yearsThanks for this. You answered my question and led me on the right path to research why this worked and I was able to adapt it to my real life code. I am updating my question with my findings.
-
mmv_sat about 8 yearsLooks like the set class is depreciated in favor of the Hash class