How do I remove specific keys from Array? PHP - php

I am trying to remove keys from array.
Here is what i get from printing print_r($cats);
Array
(
[0] => All > Computer errors > HTTP status codes > Internet terminology
[1] =>
Main
)
I am trying to use this to remove "Main" category from the array
function array_cleanup( $array, $todelete )
{
foreach( $array as $key )
{
if ( in_array( $key[ 'Main' ], $todelete ) )
unset( $array[ $key ] );
}
return $array;
}
$newarray = array_cleanup( $cats, array('Main') );
Just FYI I am new to PHP... obviously i see that i made mistakes, but i already tried out many things and they just don't seem to work

Main is not the element of array, its a part of a element of array
function array_cleanup( $array, $todelete )
{
$cloneArray = $array;
foreach( $cloneArray as $key => $value )
{
if (strpos($value, $todelete ) !== false)
unset( $array[ $key ] ); //$array[$key] = str_replace($toDelete, $replaceWith, $value) ; // add one more argument $replaceWith to function
}
return $array;
}
Edit:
with array
function array_cleanup( $array, $todelete )
{
foreach($todelete as $del){
$cloneArray = $array;
foreach( $cloneArray as $key => $value )
{
if (strpos($value, $del ) !== false)
unset( $array[ $key ] ); //$array[$key] = str_replace($toDelete, $replaceWith, $value) ; // add one more argument $replaceWith to function
}
}
return $array;
}
$newarray = array_cleanup( $cats, array('Category:Main') );

Wanted to note that while the accepted answer works there's a built in PHP function that handles this called array_filter. For this particular example it'd be something like:
public function arrayRemoveMain($var){
if ( strpos( $var, "Category:Main" ) !== false ) { return false; }
return true;
}
$newarray = array_filter( $cats, "arrayRemoveMain" );
Obviously there are many ways to do this, and the accepted answer may very well be the most ideal situation especially if there are a large number of $todelete options. With the built in array_filter I'm not aware of a way to pass additional parameters like $todelete so a new function would have to be created for each option.

It's easy.
$times = ['08:00' => '08:00','09:00' => '09:00','10:00' => '10:00'];
$timesReserved = ['08:00'];
$times = (function() use ($times, $timesReserved) {
foreach($timesReserved as $time){
unset($times[$time]);
}
return $times;
})();

The question is "how do I remove specific keys".. So here's an answer with array filter if you're looking to eliminate keys that contain a specific string, in our example if we want to eliminate anything that contains "alt_"
$arr = array(
"alt_1"=>"val",
"alt_2" => "val",
"good key" => "val"
);
function remove_alt($k) {
if(strpos($k, "alt_") !== false) {
# return false if there's an "alt_" (won't pass array_filter)
return false;
} else {
# all good, return true (let it pass array_filter)
return true;
}
}
$new = array_filter($arr,"remove_alt",ARRAY_FILTER_USE_KEY);
# ^ this tells the script to enable the usage of array keys!
This will return
array(""good key" => "val");

Related

In Array with regex

I`m using $_POST array with results of checkbox's selected from a form.
I'm thinking of using php in_array function but how could I extract only values that start with chk Given the following array:
Array (
[chk0] => 23934567622639616
[chk3] => 23934567622639618
[chk4] => 23934567622639619
[select-all] => on
[process] => Process
)
Thanks!
Simple and fast
$result=array();
foreach($_POST as $key => $value){
if(substr($key, 0, 2) == 'chk'){
$result[$key] = $value;
}
}
Lots of ways to do this, I like array_filter.
Example:
$result = array_filter(
$_POST,
function ($key) {
return strpos($key, "chk") === 0;
},
ARRAY_FILTER_USE_KEY
);
Here's a solution from http://php.net/manual/en/function.preg-grep.php
<?php
function preg_grep_keys($pattern, $input, $flags = 0) {
return array_intersect_key($input, array_flip(preg_grep($pattern, array_keys($input), $flags)));
}
?>
I would use array_filter
$ary = array_filter($originalArray,
function($key){ return preg_match('/chk/', $key); },
ARRAY_FILTER_USE_KEY
);

check if association keys exists in a particular array

I'm trying to build a function that checks if there's a value at a particular location in an array:
function ($array, $key) {
if (isset($array[$key]) {
return true;
}
return false;
}
but how can I accomplish this in a multi array? say I want to check if a value is set on $array[test1][test2]
Pass an array of keys, and recurse into the objects you find along the way:
function inThere($array, $keys)
{
$key = $keys; // if a single key was passed, use that
$rest = array();
// else grab the first key in the list
if (is_array($keys))
{
$key = $keys[0];
$rest = array_slice($keys, 1);
}
if (isset($array[$key]))
{
if (count($rest) > 0)
return inThere($array[$key], $rest);
else
return true;
}
return false;
}
So, for:
$foo = array(
'bar' => array( 'baz' => 1 )
);
inThere($foo, 'bar'); // == true
inThere($foo, array('bar')); // == true
inThere($foo, array('bar', 'baz')); // == true
inThere($foo, array('bar', 'bazX')); // == false
inThere($foo, array('barX')); // == false
Here is a non-recursive way to check for if a multi-level hashtable is set.
// $array it the container you are testing.
// $keys is an array of keys that you want to check. [key1,key2...keyn]
function ($array, $keys) {
// Is the first key set?
if (isset($array[$key]) {
// Set the test to the value of the first key.
$test = $array[$key];
for($i = 1; $i< count($keys); $i++){
if (!isset($test[$keys[$i]]) {
// The test doesn't have a matching key, return false
return false;
}
// Set the test to the value of the current key.
$test = $test[$keys[$i]];
}
// All keys are set, return true.
return true;
} else {
// The first key doesn't exist, so exit.
return false;
}
}
While I probably wouldn't build a function for this, perhaps you can put better use to it:
<?php
function mda_isset( $array )
{
$args = func_get_args();
unset( $args[0] );
if( count( $args ) > 0 )
{
foreach( $args as $x )
{
if( array_key_exists( $x, $array ) )
{
$array = $array[$x];
}
else
{
return false;
}
}
if( isset( $array ) )
{
return true;
}
}
return false;
}
?>
You can add as many arguments as required:
// Will Test $array['Test1']['Test2']['Test3']
$bool = mda_isset( $array, 'Test1', 'Test2', 'Test3' );
It will first check to make sure the array key exists, set the array to that key, and check the next key. If the key is not found, then you know it doesn't exist. If the keys are all found, then the value is checked if it is set.
I'm headed out, but maybe this. $keys should be an array even if one, but you can alter the code to check for an array of keys or just one:
function array_key_isset($array, $keys) {
foreach($keys as $key) {
if(!isset($array[$key])) return false;
$array = $array[$key];
}
return true;
}
array_key_isset($array, array('test1','test2'));
There's more universal method but it might look odd at first:
Here we're utilizing array_walk_recursive and a closure function:
$array = array('a', 'b', array('x', 456 => 'y', 'z'));
$search = 456; // search for 456
$found = false;
array_walk_recursive($array, function ($value, $key) use ($search, &$found)
{
if ($key == $search)
$found = true;
});
if ($found == true)
echo 'got it';
The only drawback is that it will iterate over all values, even if it's already found the key. This is good for small array though

PHP variable variable array key list

I have a multidimensional array where this works:
print_r( $temp[1][0] );
How can I make this work... I have the list of keys as a string like this:
$keys = "[1][0]";
I want to access the array using the string list of keys, how can it be done?
This works but the keys are obviously hard coded:
$keys = "[1][0]";
$tempName = 'temp';
print_r( ${$tempName}[1][0] );
// tried lots of variations like, but they all produce errors or don't access the array
print_r( ${$tempName.${$keys}} );
Thanks,
Chris
function accessArray(array $array, $keys) {
if (!preg_match_all('~\[([^\]]+)\]~', $keys, $matches, PREG_PATTERN_ORDER)) {
throw new InvalidArgumentException;
}
$keys = $matches[1];
$current = $array;
foreach ($keys as $key) {
$current = $current[$key];
}
return $current;
}
echo accessArray(
array(
1 => array(
2 => 'foo'
)
),
'[1][2]'
); // echos 'foo'
Would be even nicer, if you passed in array(1, 2), instead of [1][2]: One could avoid the (fragile) preg_match_all parsing.

generic function for extracting values from an array with one particular key in PHP

Is it possible in PHP to extract values from an array with a particular key path and return an array of those values? I'll explain with an example:
$user =
array (
array(
'id' => 1,
'email' =>'asd#example.com',
'project' => array ('project_id' => 222, 'project_name' => 'design')
),
array(
'id' => 2,
'email' =>'asd2#example.com',
'project' => array ('project_id' => 333, 'project_name' => 'design')
)
);
/** I have to write a function something like: */
$projectIds = extractValuesWithKey($user, array('project', 'project_id'));
print_r($projectIds);
Output:
Array(
[0] => 222,
[1] => 333
)
I would have gone for a different approach (not that there's anything wrong with the array-function-based answers) by using a recursive iterator to flatten the array which makes the key-path comparison fairly simple.
function extractValuesWithKey($array, $keys) {
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
$keys_count = count($keys);
// No point going deeper than we have to!
$iterator->setMaxDepth($keys_count);
$result = array();
foreach ($iterator as $value) {
// Skip any level that can never match our keys
if ($iterator->getDepth() !== $keys_count) {
continue;
}
// Build key path to current item for comparison
$key_path = array();
for ($depth = 1; $depth <= $keys_count; $depth++) {
$key_path[] = $iterator->getSubIterator($depth)->key();
}
// If key paths match, add to results
if ($key_path === $keys) {
$result[] = $value;
}
}
return $result;
}
To make the whole thing more useful, you could even wrap the code into a custom FilterIterator rather than a basic function, but I guess that's probably a different question entirely.
Well, that's easier than you think.
function extractValuesWithKey($array, $parts) {
$return = array();
$rawParts = $parts;
foreach ($array as $value) {
$tmp = $value;
$found = true;
foreach ($parts as $key) {
if (!is_array($tmp) || !isset($tmp[$key])) {
$found = false;
continue;
} else {
$tmp = $tmp[$key];
}
}
if ($found) {
$return[] = $tmp;
}
}
return $return;
}
If the 'key path' isn't dynamic, you can do a one-liner with array_map:
$projectIds = array_map(function($arr) { return $arr['project']['project_id']; }, $user);
Alternatively, for dynamic paths:
function extractValuesWithKey($users, $path) {
return array_map(function($array) use ($path) {
array_walk($path, function($key) use (&$array) { $array = $array[$key]; });
return $array;
}, $users);
}
The closures/anonymous functions only work with PHP 5.3+, and I've no idea how this would compare performance-wise to a double foreach loop. Note also that there's no error checking to ensure that the path exists.
I also used a similiar function in one of my projects, maybe you find this useful:
function extractValuesWithKey($data, $path) {
if(!count($path)) return false;
$currentPathKey = $path[0];
if(isset($data[$currentPathKey])) {
$value = $data[$currentPathKey];
return is_array($value) ? extractValuesWithKey($value, array_slice($path, 1)) : $value;
}
else {
$tmp = array();
foreach($data as $key => $value) {
if(is_array($value)) $tmp[] = extractValuesWithKey($value, $path);
}
return $tmp;
}
}

Determine if a PHP array uses keys or indices [duplicate]

This question already has answers here:
How to check if PHP array is associative or sequential?
(60 answers)
Closed 9 years ago.
How do I find out if a PHP array was built like this:
array('First', 'Second', 'Third');
Or like this:
array('first' => 'First', 'second' => 'Second', 'third' => 'Third');
???
I have these simple functions in my handy bag o' PHP tools:
function is_flat_array($ar) {
if (!is_array($ar))
return false;
$keys = array_keys($ar);
return array_keys($keys) === $keys;
}
function is_hash($ar) {
if (!is_array($ar))
return false;
$keys = array_keys($ar);
return array_keys($keys) !== $keys;
}
I've never tested its performance on large arrays. I mostly use it on arrays with 10 or fewer keys so it's not usually an issue. I suspect it will have better performance than comparing $keys to the generated range 0..count($array).
print_r($array);
There is no difference between
array('First', 'Second', 'Third');
and
array(0 => 'First', 1 => 'Second', 2 => 'Third');
The former just has implicit keys rather than you specifying them
programmatically, you can't. I suppose the only way to check in a case like yours would be to do something like:
foreach ($myarray as $key => $value) {
if ( is_numeric($key) ) {
echo "the array appears to use numeric (probably a case of the first)";
}
}
but this wouldn't detect the case where the array was built as $array = array(0 => "first", 1 => "second", etc);
function is_assoc($array) {
return (is_array($array)
&& (0 !== count(array_diff_key($array, array_keys(array_keys($array))))
|| count($array)==0)); // empty array is also associative
}
here's another
function is_assoc($array) {
if ( is_array($array) && ! empty($array) ) {
for ( $i = count($array) - 1; $i; $i-- ) {
if ( ! array_key_exists($i, $array) ) { return true; }
}
return ! array_key_exists(0, $array);
}
return false;
}
Gleefully swiped from the is_array comments on the PHP documentation site.
That's a little tricky, especially that this form array('First', 'Second', 'Third'); implicitly lets PHP generate keys values.
I guess a valid workaround would go something like:
function array_indexed( $array )
{
$last_k = -1;
foreach( $array as $k => $v )
{
if( $k != $last_k + 1 )
{
return false;
}
$last_k++;
}
return true;
}
If you have php > 5.1 and are only looking for 0-based arrays, you can shrink the code to
$stringKeys = array_diff_key($a, array_values($a));
$isZeroBased = empty($stringKeys);
I Hope this will help you
Jerome WAGNER
function isAssoc($arr)
{
return $arr !== array_values($arr);
}

Categories