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))));
Related
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);
I have two arrays, array1 and array2 that I am using to populate a table, so that array1[5] and array2[5] both fill the same row but I want to write a function that removes both array1[i] and array2[i] if array1[i] is a duplicate of array1[j] for some j less than i, where i is an arbitrary positive integer.
To accomplish this I was to work out the indices of duplicate values in array1 and then use this information to delete the entries from both array1 and array2 for these indices, before populating my table.
Any ideas gratefully received.
Thanks.
The array_unique function removes dupes, but preserves keys. Then you can just iterate through the other array and remove the keys that don't exist in the first one.
$array1 = array_unique($array1);
foreach ($array2 as $key => $val) {
if (!array_key_exists($key,$array1)) unset($array2[$key]);
}
$array1_keys = array_keys($array1); // all keys
$unique = array_keys(array_unique($array1)); // keys of unique values
$duplicate = array_diff($array1_keys, $unique_keys); // keys of the duplicate values
foreach($duplicate as $key){
unset($array2[$key]);
}
Sidenote: Be aware that array_diff uses string casting for comparison. If your array contains non scalar values you should have a look at array_udiff.
Edit: Mingos post in my eyes did not fully suit the question, looks like i was wrong :D
If your array keys are meaningful and not just a 0-based index and you want to keep the duplicate entry with the lowest key (as you indicate might be the case from your question) then you need to sort the array first. If you don't, you will get the first entry in the array for each duplicate value and not entry with the lowest key. Compare
$array = array( 5 => 'foo', 1 => 'bar', 2 => 'foo', 3 => 'bar' );
$array = array_unique( $array );
var_dump( $array );
with
$array = array( 5 => 'foo', 1 => 'bar', 2 => 'foo', 3 => 'bar' );
ksort( $array );
$array = array_unique( $array );
var_dump( $array );
In asociative arrays, you can get easily a counter of item to detect repeated and the first ocurrence with something as simple as (in this case using an associative array, where $array_key is the key to count) using array_count_values:
$index = null;
$array_by_columns = array_count_values(array_column($associative_array, $array_key);
foreach($array_by_columns) as $key => $ocurrences){
if($ocurrences > 1){
$index = $key;
}
}
If you have $index there are repeated element and also is the index of in the array.
A more compacted way in a line:
$index = null;
foreach(array_count_values(array_column($associative_array, $array_key)) as $key => $ocurrences)if($ocurrences > 1) $index = $key;
Data example:
[ARRAY] (start)
n0
KEY = 0
VALUE = {"user":"1","points":"10"}
n1
KEY = 1
VALUE = {"user":"4","points":"10"}
n2
KEY = 2
VALUE = {"user":"5","points":"30"}
n3
KEY = 3
VALUE = {"user":"1","points":"40"}
[ARRAY] (end)
More info:
array_count_values
array_column
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
array(
[0]
name => 'joe'
size => 'large'
[1]
name => 'bill'
size => 'small'
)
I think i'm being thick, but to get the attributes of an array element if I know the value of one of the keys, I'm first looping through the elements to find the right one.
foreach($array as $item){
if ($item['name'] == 'joe'){
#operations on $item
}
}
I'm aware that this is probably very poor, but I am fairly new and am looking for a way to access this element directly by value. Or do I need the key?
Thanks,
Brandon
If searching for the exact same array it will work, not it you have other values in it:
<?php
$arr = array(
array('name'=>'joe'),
array('name'=>'bob'));
var_dump(array_search(array('name'=>'bob'),$arr));
//works: int(1)
$arr = array(
array('name'=>'joe','a'=>'b'),
array('name'=>'bob','c'=>'d'));
var_dump(array_search(array('name'=>'bob'),$arr));
//fails: bool(false)
?>
If there are other keys, there is no other way then looping as you already do. If you only need to find them by name, and names are unique, consider using them as keys when you create the array:
<?php
$arr = array(
'joe' => array('name'=>'joe','a'=>'b'),
'bob' => array('name'=>'bob','c'=>'d'));
$arr['joe']['a'] = 'bbb';
?>
Try array_search
$key = array_search('joe', $array);
echo $array[$key];
If you need to do operations on name, and name is unique within your array, this would be better:
array(
'joe'=> 'large',
'bill'=> 'small'
);
With multiple attributes:
array(
'joe'=>array('size'=>'large', 'age'=>32),
'bill'=>array('size'=>'small', 'age'=>43)
);
Though here you might want to consider a more OOP approach.
If you must use a numeric key, look at array_search
You can stick to your for loop. There are not big differences between it and other methods – the array has always to be traversed linearly. That said, you can use these functions to find array pairs with a certain value:
array_search, if you're there's only one element with that value.
array_keys, if there may be more than one.
In PHP, what's the best way to copy an array and keep the keys with empty values?
array1 = array("apple" => "green", "banana" => "yellow);
I want to copy array1 to array2 and keep only the keys...
array2 = array("apple" => "", "banana" => "");
return array_fill_keys(array_keys($array1), "");
(Example run: http://www.ideone.com/SuMt2)
What about array_keys(), it return an array that has the keys of another array as values.
You can then use array_flip() to change keys for values and voilá, you have your result.
In a nutshell:
$array2 = array_flip(array_keys($array1));
you can use foreach to produce a new array, or one of numerous array functions