I have an associative array of data and I have an array of keys I would like to remove from that array (while keeping the remaining keys in original order -- not that this is likely to be a constraint).
I am looking for a one liner of php to do this.
I already know how I could loop through the arrays but it seems there should be some array_map with unset or array_filter solution just outside of my grasp.
I have searched around for a bit but found nothing too concise.
To be clear this is the problem to do in one line:
//have this example associative array of data
$data = array(
'blue' => 43,
'red' => 87,
'purple' => 130,
'green' => 12,
'yellow' => 31
);
//and this array of keys to remove
$bad_keys = array(
'purple',
'yellow'
);
//some one liner here and then $data will only have the keys blue, red, green
$out =array_diff_key($data,array_flip($bad_keys));
All I did was look through the list of Array functions until I found the one I needed (_diff_key).
The solution is indeed the one provided by Niet the Dark Absol. I would like to provide another similar solution for anyone who is after similar thing, but this one uses a whitelist instead of a blacklist:
$whitelist = array( 'good_key1', 'good_key2', ... );
$output = array_intersect_key( $data, array_flip( $whitelist ) );
Which will preserve keys from $whitelist array and remove the rest.
This is a blacklisting function I created for associative arrays.
if(!function_exists('array_blacklist_assoc')){
/**
* Returns an array containing all the entries from array1 whose keys are not present in any of the other arrays when using their values as keys.
* #param array $array1 The array to compare from
* #param array $array2 The array to compare against
* #return array $array2,... More arrays to compare against
*/
function array_blacklist_assoc(Array $array1, Array $array2) {
if(func_num_args() > 2){
$args = func_get_args();
array_shift($args);
$array2 = call_user_func_array('array_merge', $args);
}
return array_diff_key($array1, array_flip($array2));
}
}
$sanitized_data = array_blacklist_assoc($data, $bad_keys);
Related
The question pretty much says it all.
Im trying to match the keys of one array, to the values of another in php, without the use of a loop. Thanks :)
I could create an array by naming all the keys to the value i want to match against and set the value to null and check the key intersection, but this just seems inefficient. There probably is a simpler way to it, if anyone knows :)
For example
$array1 = array('photo' => 'foo.jpeg', 'audio' => 'bar.mp3');
$array2 = array('photo', 'audio', 'video');
Im trying to get any value of $array2 to match with any of the keys of $array1
Try these methods.
<?php
$a = array_keys( array('photo' => 'foo.jpeg', 'audio' => 'bar.mp3') );
$b = array('photo', 'audio', 'video');
//This will return empty array
print_r(array_values( array_diff($a, $b) ));
//This will return array with "video".
print_r(array_values( array_diff($b, $a) ));
//This will check Double sided array so the response
// will be element missing from both arrays.
print_r(array_values(array_merge(array_diff($b, $a), array_diff($a, $b))));
So far all my research has shown that this cannot be achieved without writing lengthy functions such as the solution here
Surely there is a simpler way of achieving this using the predefined PHP functions?
Just to be clear, I am trying to do the following:
$test = array(
'bla' => 123,
'bla2' => 1234,
'bla3' => 12345
);
// Call some cool function here and return the array where the
// the element with key 'bla2' has been shifted to the beginning like so
print_r($test);
// Prints bla2=1234, bla=>123 etc...
I have looked at using the following functions but have so far have not been able to write a solution myself.
array_unshift
array_merge
To Summarize
I would like to:
Move an element to the beginning of an array
... whilst maintaining the associative array keys
This seems, funny, to me. But here ya go:
$test = array(
'bla' => 123,
'bla2' => 1234,
'bla3' => 12345
);
//store value of key we want to move
$tmp = $test['bla2'];
//now remove this from the original array
unset($test['bla2']);
//then create a new array with the requested index at the beginning
$new = array_merge(array('bla2' => $tmp), $test);
print_r($new);
Output looks like:
Array
(
[bla2] => 1234
[bla] => 123
[bla3] => 12345
)
You could turn this into a simple function that takes-in a key and an array, then outputs the newly sorted array.
UPDATE
I'm not sure why I didn't default to using uksort, but you can do this a bit cleaner:
$test = array(
'bla' => 123,
'bla2' => 1234,
'bla3' => 12345
);
//create a function to handle sorting by keys
function sortStuff($a, $b) {
if ($a === 'bla2') {
return -1;
}
return 1;
}
//sort by keys using user-defined function
uksort($test, 'sortStuff');
print_r($test);
This returns the same output as the code above.
This isn't strictly the answer to Ben's question (is that bad?) - but this is optimised for bringing a list of items to the top of the list.
/**
* Moves any values that exist in the crumb array to the top of values
* #param $values array of options with id as key
* #param $crumbs array of crumbs with id as key
* #return array
* #fixme - need to move to crumb Class
*/
public static function crumbsToTop($values, $crumbs) {
$top = array();
foreach ($crumbs AS $key => $crumb) {
if (isset($values[$key])) {
$top[$key] = $values[$key];
unset($values[$key]);
}
}
return $top + $values;
}
This question already has answers here:
How to get an array of specific "key" in multidimensional array without looping [duplicate]
(4 answers)
Closed 1 year ago.
I have a multidimensional array, that has say, x number of columns and y number of rows.
I want specifically all the values in the 3rd column.
The obvious way to go about doing this is to put this in a for loop like this
for(i=0;i<y-1;i++)
{
$ThirdColumn[] = $array[$i][3];
}
but there is an obvious time complexity of O(n) involved here. Is there a built in way for me to simply extract each of these rows from the array without having to loop in.
For example (this does not work offcourse)
$ThirdColumn = $array[][3]
Given a bidimensional array $channels:
$channels = array(
array(
'id' => 100,
'name' => 'Direct'
),
array(
'id' => 200,
'name' => 'Dynamic'
)
);
A nice way is using array_map:
$_currentChannels = array_map(function ($value) {
return $value['name'];
}, $channels);
and if you are a potentate (php 5.5+) through array_column:
$_currentChannels = array_column($channels, 'name');
Both results in:
Array
(
[0] => Direct
[1] => Dynamic
)
Star guests:
array_map (php4+) and array_column (php5.5+)
// array array_map ( callable $callback , array $array1 [, array $... ] )
// array array_column ( array $array , mixed $column_key [, mixed $index_key = null ] )
Is there a built in way for me to simply extract each of these rows from the array without having to loop in.
Not yet. There will be a function soon named array_column(). However the complexity will be the same, it's just a bit more optimized because it's implemented in C and inside the PHP engine.
Try this....
foreach ($array as $val)
{
$thirdCol[] = $val[2];
}
Youll endup with an array of all values from 3rd column
Another way to do the same would be something like $newArray = array_map( function($a) { return $a['desiredColumn']; }, $oldArray ); though I don't think it will make any significant (if any) improvement on the performance.
You could try this:
$array["a"][0]=10;
$array["a"][1]=20;
$array["a"][2]=30;
$array["a"][3]=40;
$array["a"][4]=50;
$array["a"][5]=60;
$array["b"][0]="xx";
$array["b"][1]="yy";
$array["b"][2]="zz";
$array["b"][3]="aa";
$array["b"][4]="vv";
$array["b"][5]="rr";
$output = array_slice($array["b"], 0, count($array["b"]));
print_r($output);
I have an array:
$ids = array(1 => '3010', 2 => '10485', 3 => '5291');
I want to create a new array that takes the values of the $ids array and sets them as the keys of a new array, having the same value.
The final array would be:
$final = array('3010' => 'Green', '10485' => 'Green', '5291' => 'Green');
This will be used in apc_add().
I know I can accomplish this by looping thru it.
$final = array();
foreach($ids as $key => $value):
$final[$value] = 'Green';
endforeach;
But I was wondering if there was php function that does this without having to use a forloop, thanks!
You are looking for array_fill_keys.
$final = array_fill_keys($ids, "Green");
However, be aware that strings that are decimal representations of integers are actually converted to integers when used as array keys. This means that in your example the numbers that end up as keys in $final will have been transformed to integers. Most likely won't make a difference in practice, but you should know about it.
You can do with array_fill_keys this way:
$final = array_fill_keys($ids, "Green");
I remember that there were function that have such functionality. Unfortunately, I don't remember the name of it. Basically, it did something like...
$values = foo(array('x', 'y', 'z'), $_POST);
If there are such keys in the array, it does return new array (named $values) with only those keys... taken from $_POST. If one or more keys aren't in $_POST, it simply returns false.
Anyone remember something like that or I was just dreaming? Thanks in advice!
http://www.php.net/manual/en/function.array-intersect-key.php
I think the function you are looking for is array_intersect_key() As of PHP 5.1.0.
array array_intersect_key ( array $array1 , array $array2 [, array $ ... ] )
Parameters
array1 - The array with master keys to check.
array2 - An array to compare keys against.
array - A variable list of arrays to compare.
Returns an associative array containing all the entries of array1 which have keys that are present in all arguments.
check out this function array_key_exists
<?php
$search_array = array('first' => 1, 'second' => 4);
if (array_key_exists('first', $search_array))
{
echo "The 'first' element is in the array";
}
?>
http://www.php.net/manual/en/function.array-key-exists.php