I know there is array_unique function, but I want to remove duplicates. Is there a built-in function or do I have to roll my own.
Example input:
banna, banna, mango, mango, apple
Expected output:
apple
You can use a combination of array_unique, array_diff_assoc and array_diff:
array_diff($arr, array_diff_assoc($arr, array_unique($arr)))
You can use
$singleOccurences = array_keys(
array_filter(
array_count_values(
array('banana', 'mango', 'banana', 'mango', 'apple' )
),
function($val) {
return $val === 1;
}
)
)
See
array_count_values — Counts all the values of an array
array_filter — Filters elements of an array using a callback function
array_keys — Return all the keys or a subset of the keys of an array
callbacks
Just write your own simple foreach loop:
$used = array();
$array = array("banna","banna","mango","mango","apple");
foreach($array as $arrayKey => $arrayValue){
if(isset($used[$arrayValue])){
unset($array[$used[$arrayValue]]);
unset($array[$arrayKey]);
}
$used[$arrayValue] = $arrayKey;
}
var_dump($array); // array(1) { [4]=> string(5) "apple" }
have fun :)
If you want to only leave values in the array that are already unique, rather than select one unique instance of each value, you will indeed have to roll your own. Built in functionality is just there to sanitise value sets, rather than filter.
You want to remove any entries that have duplicates, so that you're left with only the entries that were unique in the list?
Hmm it does sound like something you'll need to roll your own.
There is no existing function; You'll have to do this in two passes, one to count the unique values and one to extract the unique values:
$count = array();
foreach ($values as $value) {
if (array_key_exists($value, $count))
++$count[$value];
else
$count[$value] = 1;
}
$unique = array();
foreach ($count as $value => $count) {
if ($count == 1)
$unique[] = $value;
}
The answer on top looks great, but on a side note: if you ever want to eliminate duplicates but leave the first one, using array_flip twice would be a pretty simple way to do so. array_flip(array_flip(x))
Only partially relevant to this specific question - but I created this function from Gumbo's answer for multi dimensional arrays:
function get_default($array)
{
$default = array_column($array, 'default', 'id');
$array = array_diff($default, array_diff_assoc($default, array_unique($default)));
return key($array);
}
In this example, I had cached statuses and each one other than the default was 0 (the default was 1). I index the default array from the IDs, and then turn it into a string. So to be clear - the returned result of this is the ID of the default status providing it's in the same part of the multi dimensional array and not the key of it
PHP.net http://php.net/manual/en/function.array-unique.php
array array_unique ( array $array [, int $sort_flags = SORT_STRING ] )
Takes an input array and returns a new array without duplicate values.
New solution:
function remove_dupes(array $array){
$ret_array = array();
foreach($array as $key => $val){
if(count(array_keys($val) > 1){
continue;
} else {
$ret_array[$key] = $val;
}
}
Related
I need to remove values from an array that occur more than one time in the array.
For example:
$value = array(10,10,5,8);
I need this result:
$value = array(5,8);
Is there any in-built function in php?
I tried this, but this will not return my expected result:
$unique = array_unique($value);
$dupes = array_diff_key($value, $unique);
You can use array functions and ditch the foreach loops if you wish:
Here is a one-liner:
Code:
$value = [10, 10, 5, 8];
var_export(array_keys(array_intersect(array_count_values($value),[1])));
As multi-line:
var_export(
array_keys(
array_intersect(
array_count_values($value),
[1]
)
)
);
Output:
array (
0 => 5,
1 => 8,
)
This gets the value counts as an array, then uses array_intersect() to only retain values that occur once, then turns the keys into the values of a zero-index array.
The above snippet works identically to #modsfabio's and #axiac's answers. The ONLY advantage in my snippet is brevity. It is possible that their solutions may outperform mine, but judging speed on relatively small data sets may be a waste of dev time. For anyone processing relatively large data sets, do your own benchmarking to find the technique that works best.
For lowest computational/time complexity, use a single loop and as you iterate conditionally populate a lookup array and unset() as needed.
Code: (Demo) (Crosslink to my CodeReview answer)
$values = [10, 10, 5, 8];
$found = [];
foreach ($values as $index => $value) {
if (!isset($found[$value])) {
$found[$value] = $index;
} else {
unset($values[$index], $values[$found[$value]]);
}
}
var_export($values);
// [2 => 5, 3 => 8]
A couple of notes:
If processing float values, using a technique that stores the values as keys (as all of my snippets do), then the results may be incorrect because php will change floats to integers when used as keys.
PHP is consistently much faster at searching for keys than it is at searching for values.
You can do it like this using array_count_values() and a foreach loop:
<?php
$input = array(10,10,5,8);
$output = array();
foreach(array_count_values($input) as $value => $count)
{
if($count == 1)
{
$output[] = $value;
}
}
var_dump($output);
Output:
array(2) {
[0]=>
int(5)
[1]=>
int(8)
}
Example: https://eval.in/819461
A possible approach:
$value = array(10,10,5,8);
$output = array_keys(
array_filter(
array_count_values($value),
function ($count) {
return $count == 1;
}
)
)
array_count_values() produces an array that associates to each unique value from $value the number of times it appears in the array.
array_filter() keeps in this result only the entries (the keys) that appear only once in the original array.
array_keys() produces the desired result.
I would use array_count_values to get an array with how often every element occurs in the array. Then remove all the elements from the original array that occur more than once.
You need to use array_count_values(), array_search() and unset() functions.
<?php
$value = array(10,10,5,8);
echo '<pre>';print_r($value);echo '</pre>';
$cnt = array_count_values($value);
$dup = array();
foreach ($cnt as $k => $repeated) {
if ($repeated > 1) {
if(($key = array_search($k, $value)) !== false) {
unset($value[$key]);
}
}
}
echo '<pre>';print_r($cnt);echo '</pre>';
echo '<pre>';print_r($value);echo '</pre>';
?>
Demo
you can use
foreach loop
and
array_diff() function:
$value=array(10,10,5,8);
$duplicated=array();
foreach($value as $k=>$v)
{
if($kt=array_search($v,$value))!==false and
$k!=$kt)
{if (count(array_keys($array, $value)) > 1)
{
/* Execute code */
}
unset($value[$kt];$duplicated[]=$v;
}
}
$result=array_diff($values,$duplicated);
print_r($result);
output
Array([2]=>5[3]=>8)
I have the following two arrays:
$array_one = array('colorZero'=>'black', 'colorOne'=>'red', 'colorTwo'=>'green', 'colorThree'=>'blue', 'colorFour'=>'purple', 'colorFive'=>'golden');
$array_two = array('colorOne', 'colorTwo', 'colorThree');
I want an array from $array_one which only contains the key-value pairs whose keys are members of $array_two (either by making a new array or removing the rest of the elements from $array_one)
How can I do that?
I looked into array_diff and array_intersect, but they compare values with values, and not the values of one array with the keys of the other.
As of PHP 5.1 there is array_intersect_key (manual).
Just flip the second array from key=>value to value=>key with array_flip() and then compare keys.
So to compare OP's arrays, this would do:
$result = array_intersect_key( $array_one , array_flip( $array_two ) );
No need for any looping the arrays at all.
Update
Check out the answer from Michel: https://stackoverflow.com/a/30841097/2879722. It's a better and easier solution.
Original Answer
If I am understanding this correctly:
Returning a new array:
$array_new = [];
foreach($array_two as $key)
{
if(array_key_exists($key, $array_one))
{
$array_new[$key] = $array_one[$key];
}
}
Stripping from $array_one:
foreach($array_one as $key => $val)
{
if(array_search($key, $array_two) === false)
{
unset($array_one[$key]);
}
}
Tell me if it works:
for($i=0;$i<count($array_two);$i++){
if($array_two[$i]==key($array_one)){
$array_final[$array_two[$i]]=$array_one[$array_two[$i]];
next($array_one);
}
}
How can I delete duplicates in array?
For example if I had the following array:
$array = array('1','1','2','3');
I want it to become
$array = array('2','3');
so I want it to delete the whole value if two of it are found
Depending on PHP version, this should work in all versions of PHP >= 4.0.6 as it doesn't require anonymous functions that require PHP >= 5.3:
function moreThanOne($val) {
return $val < 2;
}
$a1 = array('1','1','2','3');
print_r(array_keys(array_filter(array_count_values($a1), 'moreThanOne')));
DEMO (Change the PHP version in the drop-down to select the version of PHP you are using)
This works because:
array_count_values will go through the array and create an index for each value and increment it each time it encounters it again.
array_filter will take the created array and pass it through the moreThanOne function defined earlier, if it returns false, the key/value pair will be removed.
array_keys will discard the value portion of the array creating an array with the values being the keys that were defined. This final step gives you a result that removes all values that existed more than once within the original array.
You can filter them out using array_count_values():
$array = array('1','1','2','3');
$res = array_keys(array_filter(array_count_values($array), function($freq) {
return $freq == 1;
}));
The function returns an array comprising the original values and their respective frequencies; you then pick only the single frequencies. The end result is obtained by retrieving the keys.
Demo
Try this code,
<?php
$array = array('1','1','2','3');
foreach($array as $data){
$key= array_keys($array,$data);
if(count($key)>1){
foreach($key as $key2 => $data2){
unset($array[$key2]);
}
}
}
$array=array_values($array);
print_r($array);
?>
Output
Array ( [0] => 2 [1] => 3 )
PHP offers so many array functions, you just have to combine them:
$arr = array_keys(array_filter(array_count_values($arr), function($val) {
return $val === 1;
}));
Reference: array_keys, array_filter, array_count_values
DEMO
Remove duplicate values from an array.
array_unique($array)
$array = array(4, "4", "3", 4, 3, "3");
$result = array_unique($array);
print_r($result);
/*
Array
(
[0] => 4
[2] => 3
)
*/
I have an array and in that array I have an array key that looks like, show_me_160 this array key may change a little, so sometimes the page may load and the array key maybe show_me_120, I want to now is possible to just string match the array key up until the last _ so that I can check what the value is after the last underscore?
one solution i can think of:
foreach($myarray as $key=>$value){
if("show_me_" == substr($key,0,8)){
$number = substr($key,strrpos($key,'_'));
// do whatever you need to with $number...
}
}
I ran into a similar problem recently. This is what I came up with:
$value = $my_array[current(preg_grep('/^show_me_/', array_keys($my_array)))];
you would have to iterate over your array to check each key separately, since you don't have the possibility to query the array directly (I'm assuming the array also holds totally unrelated keys, but you can skip the if part if that's not the case):
foreach($array as $k => $v)
{
if (strpos($k, 'show_me_') !== false)
{
$number = substr($k, strrpos($k, '_'));
}
}
However, this sounds like a very strange way of storing data, and if I were you, I'd check if there's not an other way (more efficient) of passing data around in your application ;)
to search for certain string in array keys you can use array_filter(); see docs
// the array you'll search in
$array = ["search_1"=>"value1","search_2"=>"value2","not_search"=>"value3"];
// filter the array and assign the returned array to variable
$foo = array_filter(
// the array you wanna search in
$array,
// callback function to search for certain sting
function ($key){
return(strpos($key,'search_') !== false);
},
// flag to let the array_filter(); know that you deal with array keys
ARRAY_FILTER_USE_KEY
);
// print out the returned array
print_r($foo);
if you search in the array values you can use the flag 0 or leave the flag empty
$foo = array_filter(
// the array you wanna search in
$array,
// callback function to search for certain sting
function ($value){
return(strpos($value,'value') !== false);
},
// flag to let the array_filter(); know that you deal with array value
0
);
or
$foo = array_filter(
// the array you wanna search in
$array,
// callback function to search for certain sting
function ($value){
return(strpos($value,'value') !== false);
}
);
if you search in the array values and array keys you can use the flag ARRAY_FILTER_USE_BOTH
$foo = array_filter(
// the array you wanna search in
$array,
// callback function to search for certain sting
function ($value, $key){
return(strpos($key,'search_') !== false or strpos($value,'value') !== false);
},
ARRAY_FILTER_USE_BOTH
);
in case you'll search for both you have to pass 2 arguments to the callback function
You can also use a preg_match based solution:
foreach($array as $str) {
if(preg_match('/^show_me_(\d+)$/',$str,$m)) {
echo "Array element ",$str," matched and number = ",$m[1],"\n";
}
}
filter_array($array,function ($var){return(strpos($var,'searched_word')!==FALSE);},);
return array 'searched_key' => 'value assigned to the key'
foreach($myarray as $key=>$value)
if(count(explode('show_me_',$event_key)) > 1){
//if array key contains show_me_
}
More information (example):
if array key contain 'show_me_'
$example = explode('show_me_','show_me_120');
print_r($example)
Array ( [0] => [1] => 120 )
print_r(count($example))
2
print_r($example[1])
120
I need to get the keys from values that are duplicates. I tried to use array_search and that worked fine, BUT I only got the first value as a hit.
I need to get both keys from the duplicate values, in this case 0 and 2. The search result output as an array would be good.
Is there a PHP function to do this or do I need to write some multiple loops to do it?
$list[0][0] = "2009-09-09";
$list[0][1] = "2009-05-05";
$list[0][2] = "2009-09-09";
$list[1][0] = "first-paid";
$list[1][1] = "1";
$list[1][2] = "last-unpaid";
echo array_search("2009-09-09",$list[0]);
You want array_keys with the search value
array_keys($list[0], "2009-09-09");
which will return an array of the keys with the specified value, in your case [0, 2]. If you want to find the duplicates as well, you can first make a pass with array_unique, then iterate over that array using array_keys on the original; anything which returns an array of length > 1 is a duplicate, and the result is the keys in which the duplicates are stored. Something like...
$uniqueKeys = array_unique($list[0])
foreach ($uniqueKeys as $uniqueKey)
{
$v = array_keys($list[0], $uniqueKey);
if (count($v) > 1)
{
foreach ($v as $key)
{
// Work with $list[0][$key]
}
}
}
In array_search() we can read:
If needle is found in haystack more
than once, the first matching key is
returned. To return the keys for all
matching values, use array_keys() with
the optional search_value parameter
instead.
The following combination of function calls will give you all duplicate values:
$a = array(1, 1, 2, 3, 4, 5, 99, 2, 5, 2);
$unique = array_unique($a); // preserves keys
$diffkeys = array_diff_key($a, $unique);
$duplicates = array_unique($diffkeys);
echo 'Duplicates: ' . join(' ', $duplicates) . "\n"; // 1 2 5
You can achieve that using array_search() by using while loop and the following workaround:
while (($key = array_search("2009-09-09", $list[0])) !== FALSE) {
print($key);
unset($list[0][$key]);
}
Source: cue at openxbox at php.net
For one-multidimensional array, you may use the following function to achieve that (as alternative to array_keys()):
function array_isearch($str, $array){
$found = array();
foreach ($array as $k => $v) {
if (strtolower($v) == strtolower($str)) {
$found[] = $k;
}
}
return $found;
}
Source: robertark, php.net
The PHP manual states in the Return Value section of the array_search() function documentation that you can use array_keys() to accomplish this. You just need to provide the second parameter:
$keys = array_keys($list[0], "2009-09-09");
$userdb=Array
(
(0) => Array
(
(uid) => '100',
(name) => 'Sandra Shush',
(url) => 'urlof100'
),
);
$key = array_search(100, array_column($userdb, 'uid'));