Remove duplicates from a multi-dimensional array based on 2 values - php

I have an array that looks like this
$array = array(
array("John","Smith","1"),
array("Bob","Barker","2"),
array("Will","Smith","2"),
array("Will","Smith","4")
);
In the end I want the array to look like this
$array = array(
array("John","Smith","1"),
array("Bob","Barker","2"),
array("Will","Smith","2")
);
The array_unique with the SORT_REGULAR flag checks for all three value. I've seen some solutions on how to remove duplicates based on one value, but I need to compare the first two values for uniqueness.

Simple solution using foreach loop and array_values function:
$arr = array(
array("John","Smith","1"), array("Bob","Barker","2"),
array("Will","Smith","2"), array("Will","Smith","4")
);
$result = [];
foreach ($arr as $v) {
$k = $v[0] . $v[1]; // considering first 2 values as a unique key
if (!isset($result[$k])) $result[$k] = $v;
}
$result = array_values($result);
print_r($result);
The output:
Array
(
[0] => Array
(
[0] => John
[1] => Smith
[2] => 1
)
[1] => Array
(
[0] => Bob
[1] => Barker
[2] => 2
)
[2] => Array
(
[0] => Will
[1] => Smith
[2] => 2
)
)

Sample code with comments:
// array to store already existing values
$existsing = array();
// new array
$filtered = array();
foreach ($array as $item) {
// Unique key
$key = $item[0] . ' ' . $item[1];
// if key doesn't exists - add it and add item to $filtered
if (!isset($existsing[$key])) {
$existsing[$key] = 1;
$filtered[] = $item;
}
}

For fun. This will keep the last occurrence and eliminate the others:
$array = array_combine(array_map(function($v) { return $v[0].$v[1]; }, $array), $array);
Map the array and build a key from the first to entries of the sub array
Use the returned array as keys in the new array and original as the values
If you want to keep the first occurrence then just reverse the array before and after:
$array = array_reverse($array);
$array = array_reverse(array_combine(array_map(function($v) { return $v[0].$v[1]; },
$array), $array));

Related

Convert array in string with another array

I have a two array first is:
$array1 = ['settings:rules:key','settings:scrum:way:other'];
I have explode $array1:
$temp_array = explode(":",$array1);
Now I have another array:
$array2 = [settings] => Array
( [rules] => Array
(
[0] => Array
(
[key] =>
[showValueField] => 1
)
)
something like this.
I need to access second array with key given in first array like:
$array2['settings']['rules']['key']
I have to get this keys from first array after explode
You can do it with this kind of loop:
function getVal($path, $arr) {
$current = $arr[array_shift($path)];
while (count($path)) {
$key = array_shift($path);
if (!is_array($current) || !isset($current[$key]))
return false; // protect against non-existing keys
$current = $current[$key];
}
return $current;
}
//example used:
$arr = array("settings" => array("rules" => array("key" => "AAA")));
echo getVal(explode(":",'settings:rules:key'), $arr) . PHP_EOL;

Fetch specific array from multidimensional array with matching value php

I have 2 arrays -
$array1 =
Array
(
[0] => Array
(
[user_id] => 2
[like_status] => 1
)
[1] => Array
(
[user_id] => 3
[like_status] => 1
)
)
$array2 =
Array
(
[isLoggedIn] => 1
[userId] => 3
)
My requirement is I want to fetch the array where userId = 3. There can be multiple records in $array1 But I only want to fetch the array which have userID = 3, which is in $array2
I am able to get into the condition and match but not able to fetch.
if(array_search($array2['userId'], array_column($array1, 'user_id')) !== False) {
print_r($array1);
}
But it should only return the specific array.
One method is to create a flat array of the userid and use array_intersect to get the matching full arrays.
$userids = array_column($array1, "user_id");
$matching = array_intersect_key($array1, array_intersect($userids, [$array2['user_id']]));
Now $matching will be all the $array1 subarrays where userid is matching $array2['userId'].
array_search($array2['userId'], array_column($array1, 'user_id'))
Will return the index of a matching item or false if there is no matching item. You can use this info to grab the array from $array1.
I.e.
$index = array_search($array2['userId'], array_column($array1, 'user_id')) !== False);
if($index !== false){
print_r($array1[$index]);
}
Note that this assumes that there is only one matching user id in the array - if there are more only the first will be found.
You can do this using foreach also, if you want to like below
foreach ($array1 as $key => $value) {
if($value['user_id'] == $array2['userId'])
{
echo '<pre>'; print_r($value);echo '</pre>';
break;
}
}
Output :
Array (
[user_id] => 3
[like_status] => 1 )
you can achieve this using foreach loop
foreach( $array1 as $val ){
$val['user_id'] == $array2['userId'] ? $result[] = $val : '';
}
echo "<pre>"; print_r( $result );

PHP - Delete all duplicates in array

How can I delete duplicates from multiple arrays?
pinky and cocos are double in my array. All words which are double, must be removed. If those are removed, I will put these words in my select.
I get those words from my database.
The query:
$queryClient = " SELECT DISTINCT `clients` FROM `reps` WHERE `clients` != ''";
This is my code:
while($row = mysql_fetch_assoc($resultClient)){
$names = explode(",", $row['clients']);
echo '<pre>'; print_r($names); echo '</pre>';
}
Result: (Those food words are just an example)
Array
(
[0] => chocolate
)
Array
(
[0] => vanilla
[0] => cocos
)
Array
(
[0] => strawberry
)
Array
(
[0] => pinky
[1] => watermelon
[2] => melon
[3] => cocos
)
Array
(
[0] => pinky
)
Array
(
[0] => dark-chocolate
)
I tried this in my while loop but it did not work:
$array = array_unique($names, SORT_REGULAR);
How can I remove all duplicates? Can you help me or do you have a solution for my problem? Help.
Here's a one-liner:
print_r(array_unique(call_user_func_array('array_merge', $names)));
First merge all subarrays into one, then get unique values.
Full example:
$names = array();
while($row = mysql_fetch_assoc($resultClient)){
$names[] = explode(",", $row['clients']);
}
print_r(array_unique(call_user_func_array('array_merge', $names)));
You can just do a little trick:
Flatten, count and then remove all except the last.
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
$flatArray = [];
foreach($it as $v) {
$flatArray[] = $v; //Flatten array
}
//Note you can do array_unique on the flat array if you also need to flatten the array
$counts = array_count_values($flatArray); //Count
foreach ($array as &$subarray) {
foreach ($subarray as $index => $element) {
$counts[$element]--;
if ($counts[$element] > 0) { //If there's more than 1 left remove it
unset($subarray[$index]);
}
}
}
This will remove duplicates nested exactly on the 2nd level without flattening the original array.
http://sandbox.onlinephpfunctions.com/code/346fd868bc89f484dac48d12575d678f3cb53626
first you need to join your array before you can filter out the duplicates:
<?php
$allNames = [];
while($row = mysql_fetch_assoc($resultClient)){
$names = explode(",", $row['food']);
$allNames[] = $names;
}
$allNames = array_merge(...$allNames); //Join everything to a one dimensional array
$allNames = array_unique($allNames); // Only keep unique elementes
print_r($allNames);

Count how many times a value appears in this array?

I have this php array named $ids:
Array (
[0] => Array ( [id] => 10101101 )
[1] => Array ( [id] => 18581768 )
[2] => Array ( [id] => 55533322 )
[3] => Array ( [id] => 55533322 )
[4] => Array ( [id] => 64621412 )
)
And I need to make a new array containing each $ids id value, as the new keys, and the times each one appears, as the new values.
Something like this:
$newArr = array(
10101101 => 1,
18581768 => 1,
55533322 => 2,
64621412 => 1,
);
This is what I have:
$newArr = array();
$aux1 = "";
//$arr is the original array
for($i=0; $i<count($arr); $i++){
$val = $arr[$i]["id"];
if($val != $aux1){
$newArr[$val] = count(array_keys($arr, $val));
$aux1 = $val;
}
}
I supose array_keys doesn't work here because $arr has the id values in the second dimension.
So, how can I make this work?
Sorry for my bad english and thanks.
array_column will create an array of all the elements in a specific column of a 2-D array, and array_count_values will count the repetitions of each value in an array.
$newArr = array_count_values(array_column($ids, 'id'));
Or do it by hand like this where $arr is your source array and $sums is your result array.
$sums = array();
foreach($arr as $vv){
$v = $vv["id"];
If(!array_key_exists($v,$sums){
$sums[$v] = 0;
}
$sums[$v]++;
}
You can traverse your array, and sum the id appearance, live demo.
$counts = [];
foreach($array as $v)
{
#$counts[$v['id']] += 1;
}
print_r($counts);

Explode multiple comma-separated strings in a 2d array, then get all unique values

I have an 2d array which returns me this values:
Array (
[0] => Array (
[0] => wallet,pen
[1] => perfume,pen
)
[1] => Array (
[0] => perfume, charger
[1] => pen,book
).
Out of this i would like to know if it is possible to create a function which would combine the array going this way,and create a new one :
if for example [0] => Array ( [0] => wallet,pen [1] => perfume,pen ) then should be equal to
[0] => Array ( [0] => wallet,pen, perfume ) because there is a common word else do nothing.
And also after that retrieve each words as strings for further operations.
How can i make the values of such an array unique. Array ( [0] => Array ( [0] => wallet [1] => pen [2] => perfume [3] => pen) ) as there is pen twice i would like it to be deleted in this way ( [0] => Array ( [0] => wallet [1] => pen [2] => perfume) )
It's just a matter of mapping the array and combining the inner arrays:
$x = [['wallet,pen', 'perfume,pen'], ['perfume,charger', 'pen,book']];
$r = array_map(function($item) {
return array_unique(call_user_func_array('array_merge', array_map(function($subitem) {
return explode(',', $subitem);
}, $item)));
}, $x);
Demo
This first splits all the strings based on comma. They are then merged together with array_merge() and the duplicates are removed using array_unique().
See also: call_user_func_array(), array_map()
Try this :
$array = Array (Array ( "wallet,pen", "perfume,pen" ), Array ( "perfume, charger", "pen,book" ));
$res = array();
foreach($array as $key=>$val){
$temp = array();
foreach($val as $k=>$v){
foreach(explode(",",$v) as $vl){
$temp[] = $vl;
}
}
if(count(array_unique($temp)) < count($temp)){
$res[$key] = implode(",",array_unique($temp));
}
else{
$res[$key] = $val;
}
}
echo "<pre>";
print_r($res);
output :
Array
(
[0] => wallet,pen,perfume
[1] => Array
(
[0] => perfume, charger
[1] => pen,book
)
)
You can eliminate duplicate values while pushing them into your result array by assigning the tag as the key to the element -- PHP will not allow duplicate keys on the same level of an array, so any re-encountered tags will simply be overwritten.
You can use recursion or statically written loops for this task.
Code: (Demo)
$result = [];
foreach ($array as $row) {
foreach ($row as $tags) {
foreach (explode(',', $tags) as $tag) {
$result[$tag] = $tag;
}
}
}
var_export(array_values($result));
Code: (Demo)
$result = [];
array_walk_recursive(
$array,
function($v) use(&$result) {
foreach (explode(',', $v) as $tag) {
$result[$tag] = $tag;
}
}
);
var_export(array_values($result));

Categories