Removing duplicates from array + json, problem with array_unique - php

I have array something like:
Array (
[0]=>{"a":"b", "c":"d", "h":"e"}
[1]=>{"a":"b", "f":"g"}
)
How i can removing duplicates here? I'm trying array_unique, but it's not working.
Expected result:
Array (
[0]=>{"a":"b", "c":"d", "h":"e"}
[1]=>{"f":"g"}
)

In this scenario, you need to be careful with duplicate keys yet different values. So match to remove duplicates has to be on combination of both key and value.
To do this, we can collect all keys in an array say $map and have all values visited for this keys inside that key array.
Now, we can just do an in_array check to get hold of whether we got some key-value pair like this before or not.
Snippet:
$arr = [
[
'a' => 'b',
'c' => 'd',
'h' => 'e'
],
[
'a' => 'b',
'f' => 'g',
'c' => 'f'
],
[
'a' => 'd',
'c' => 'd'
]
];
$map = [];
foreach($arr as $index => $data){
foreach($data as $key => $value){
if(!isset($map[$key])) $map[$key] = [];
if(in_array($value,$map[$key])) unset($arr[$index][$key]);
else $map[$key][] = $value;
}
}
print_r($arr);
Demo: https://3v4l.org/RWcMu

You can do it with array_diff() and unset() functions. But, you need to decode this JSON values firstly:
foreach($ar as $in => &$js){
$ar[$in] = json_decode($js,true);
}
After this $ar has a view like:
Array
(
[0] => Array
(
[a] => b
[c] => d
[h] => e
)
[1] => Array
(
[a] => b
[f] => g
)
)
Here you can apply array_diff() function:
$diff = array_diff($ar[1],array_diff($ar[1],$ar[0]));
It will collect duplicates from [1] index in [0]:
Array
(
[a] => b
)
Now you can unset these values from [1] index:
foreach($diff as $ind=>$uns){
unset($ar[1][$ind]);
}
And finally you can change JSON view back:
foreach($ar as $in=>&$js){
$ar[$in] = json_encode($js);
}
Result would be:
Array
(
[0] => {"a":"b","c":"d","h":"e"}
[1] => {"f":"g"}
)
Demo
If input elements are objects, then use this loop at the first step:
foreach($ar as $in=>&$obj){
$ar[$in] = (array)$obj;
}
Demo

Related

replace specific array value with another array values in php

my 1st array values are
Array (
[0] => abc
[1] => xyz
[2] => Other
[3] => Other
[4] => pqr )
when array contains value as Other i want to replace that with below array
Array (
[0] => lmnsa
[1] => asda )
I want to do this in PHP. any help guys?
First loop over the array1 and test for the value 'Other', if found replace the value with your array2
Note the use of &$a to make the $a from the foreach loop a reference, so that it can be used to replace the original array occurance and not a copy of the array which woudl have been the result without the use of the &
$array1 = Array ( "abc","xyz","Other", "Other", "pqr" );
$array2 = Array ( "lmnsa", "asda" );
foreach ($array1 as &$a) {
if ( $a == 'Other') {
$a = $array2;
}
}
print_r($array1);
The RESULT
Array
(
[0] => abc
[1] => xyz
[2] => Array
(
[0] => lmnsa
[1] => asda
)
[3] => Array
(
[0] => lmnsa
[1] => asda
)
[4] => pqr
)
I don't really understand what result are you looking for.
If you want to just replace elements with value 'Other' with some different value:
$newValue = 'New value instead of Other';
// $newValue = ['abc' 'def']; <-- if you want to replace string by an array. It wasn't unclear what you expect to achieve from the question.
$array = ['a', 'b', 'Other', 'c', 'Other', 'd'];
foreach ($array as $idx => $element) {
if ($element === 'Other') {
$array[$idx] = $newValue;
}
}
Or if you have an array of replacements, which must gradually replace all 'Other' values:
$array = ['a', 'b', 'Other', 'c', 'Other', 'd'];
$replacements = ['New Value 1', 'New Value 2'];
$replacementIdx = 0;
foreach ($array as $idx => $element) {
// Always check if you were not run out of replacement values
if (!isset($replacements[$replacementIdx])) {
break;
}
if ($element === 'Other') {
$array[$idx] = $replacements[$replacementIdx++];
}
}
Instead of using foreach ($array as $key => $value) you may also try to replace elements by reference (see RiggsFolly answer)
Based on your request what Yamingue stated is correct. You may need to clarify what you want. Are you attempting to say if the indexed value of the array initial array is 2 and its value is "Other" to replace it with it with the equivalent value of another array with the same index number?
Its been a while since ive done php buy lets give this a go.
$array1 = Array (
0 => "abc"
1 => "xyz"
2 => "Other"
3 => "Other"
4 => "pqr" );
$array2 = Array (
0 => "lmnsa"
1 => "asda"
2 => "thg"
3 => "ris"
4 => "slrn");
Foreach($array1 as $arr1key => $arr1val) {
If($arr1val == "Other"){
$array1[$arr1key] = $array2[$arr1key];
}
}
You may need to unset the values however as i said been a while for me. Nowbif you want to embed the 2nd array into the value of the first array where it currently says other thats another story, each language is a little different on multidimensional and nested arrays so i cant speak to it.
there are several ways to do it as needed. the first is to replace it with another array like this
`
$array1 = Array (
0 => "abc"
1 => "xyz"
2 => "Other"
3 => "Other"
4 => "pqr" );
$array2 = Array (
0 => "lmnsa"
1 => "asda" );
$array1 = $array2
`

How to combine 2 array into 1 array using foreach with different key

I had 2 array with different number of key
First array:
0 =>
array (size=2)
'a' => 1
'b' => 'b'
1 =>
array (size=2)
'a' => 2
'b' => '2b'
Second array:
0 =>
array (size=2)
'a' => 1
'c' => 'c'
The 'a' is act like id but there is problem on 'b' and 'c' are not mandatory to list out.
I tried array_merge before but it quite complex for my next step so i want to know is there others solution for this?
I also tried the foreach loop but it stuck at:
foreach($first_array as $data){
$result[] = $data;
......
}
The output should like this form:
[0] => Array
(
[a] => 1,
[b] => 'b',
[c] => 'c',
)
[1] => Array
(
[a] => 2,
[b] => '2b',
)
If 'a' contains the id of the record, it would be a good idea to use this as an identifier in the result array.
$results = [];
$dataSets = [$first_array, $second_array];
foreach ($dataSets as $dataSet) {
foreach ($dataSet as $record) {
if (!isset($results[$record['a']]) {
// first occurence of this record
$results[$record['a']] = $record;
continue;
}
// next occurence of this record, merge it with existing data
$results[$record['a']] = array_merge($results[$record['a']], $record);
}
}
If the results should be a normal array (e.g. if you want to encode it to JSON and don't want an object), you'll still need to remove the ids at the end
$results = array_values($results);
It is better to use a multi-dimensional array.
For example:
$myarray = array(
array("1", "b", "c"),
array("2", "2b")
);

Group associative row data based on shared column value

I have a multidimensional array like:
Array
(
[0] => Array
(
[division] => Mymensingh
[A] => 1
)
[1] => Array
(
[division] => Dhaka
[A] => 5
)
[2] => Array
(
[division] => Mymensingh
[B] => 2
[C] => 5
)
)
I need to find the rows with matching division values and merge them in one array.
From this array, I want the output as:
Array
(
[0] => Array
(
[division] => Mymensingh
[A] => 1
[B] => 2
[C] => 5
)
[1] => Array
(
[division] => Dhaka
[A] => 5
)
)
Keys in the subarrays can be different and the subarrays may have a differing number of elements.
I think it's relatively simple to just iterate through the array and continuously merge the entries separated by "division":
function mergeByDiscriminator($input, $discriminator = 'division') {
$result = [];
foreach ($input as $array) {
$key = $array[$discriminator];
$result[$key] = array_merge(
array_key_exists($key, $result) ? $result[$key] : [],
$array
);
}
return array_values($result);
}
$result = mergeByDiscriminator($input); // $input is your array
The only solution that I can think of is as below. Of course there might be other feasable solutions, but I am giving one from my end.
$array = array(
'0' => array (
'division' => 'Mymensingh',
'A' => 1
),
'1' => array (
'division' => 'Dhaka',
'A' => 5
),
'2' => array (
'division' => 'Mymensingh',
'B' => 2,
'C' => 5
),
);
$result = array();
foreach ($array as $arr) {
if (!is_array($result[$arr['division']])) $result[$arr['division']] = array();
foreach ($arr as $key => $value) {
$result[$arr['division']][$key] = $value;
}
}
echo "<pre>"; print_r($result);
The above code is giving you the desired output. Please give it a try.
Hope this helps.
This task is concisely completed with zero iterated function calls thanks to the null coalescing operator and the union operator.
Merge each iterated row with the pre-existing data in that keyed-group. If the keyed-group has not yet been encountered merge the row with an empty array.
The union operator is suitable/reliable in this case because it is writing one associative array into another associative array.
Language Construct Iteration: (Demo)
$result = [];
foreach ($array as $row) {
$result[$row['division']] = ($result[$row['division']] ?? []) + $row;
}
var_export(array_values($result));
Functional Iteration: (Demo)
var_export(
array_values(
array_reduce(
$array,
function($result, $row) {
$result[$row['division']] = ($result[$row['division']] ?? []) + $row;
return $result;
},
[]
)
)
);

Create a 'results' array based on comparison of two two-dimensional arrays?

I have two two-dimensional arrays I'd liked to compare to one another:
$array1
Array
(
[0] => Array
(
[A] => GB
[B] => Harry
[C] => British Army
[D] => Eton College
[E] => Cressida Bonas
)
[1] => Array
(
[A] => GB
[B] => William
[C] => Royal Air Force
[D] => Eton College
[E] => Catherine Middleton
)
)
$array2
Array
(
[0] => Array
(
[A] => GB
[B] => Harry
[C] => British Army
[D] => Eton College
[E] => Cressida Bonas
)
[1] => Array
(
[A] => GB
[B] => James
[C] => British Army
[D] => Millfield
[E] => Unknown
)
)
And produce a boolean true/false results array as follows if any of the child array values differ:
$results_array
Array
(
[0] => Array
(
[0] => true
)
[1] => Array
(
[0] => false
)
)
UPDATE:
Both arrays will always have the same length parent arrays (but the child arrays values may vary in length).
I can't wrap my head around how to use foreach in a recursive manner to get the results array.
Any general ideas or advice?
You could do using == operator. Passing the first array as key-array ($k=>$arr) [since the value is another array]. Now compare the two arrays using the simple == comparison operator. You can even perform strict matching using the === operator.
<?php
$arr1=array(0=>array('A'=>'GB','B'=>'Harry','C'=>'British Army'),1=>array('A'=>'GB','B'=>'William','C'=>'Royal Air Force'));
$arr2=array(0=>array('A'=>'GB','B'=>'Harry','C'=>'British Army'),1=>array('A'=>'GB','B'=>'James','C'=>'British Army'));
foreach($arr1 as $k=>$arr)
{
$resarr[][$k]=($arr==$arr2[$k])? "true" : "false";
}
print_r($resarr);
Demo
OUTPUT :
Array
(
[0] => Array
(
[0] => true
)
[1] => Array
(
[1] => false
)
)
I don't know what you are trying to do with a foreach loop. Are you saying every array will have 2 child arrays or every child array will have 5 values? Regardless, I hope this helps you!
I would use some of these:
array_intersect
array_intersect_assoc
array_diff
array_diff_assoc
Code:
<?php
$array1 = [
[
'A' => 'GB',
'B' => 'Harry',
'C' => 'British Army',
'D' => 'Eton College',
'E' => 'Cressida Bonas',
],
[
'A' => 'GB',
'B' => 'William',
'C' => 'Royal Air Force',
'D' => 'Eton College',
'E' => 'Catherine Middleton',
]
];
// What Values are in common
$result1 = array_intersect_assoc($array1[0], $array1[1]);
print_r($result1);
$array2 = [
[
'A' => 'GB',
'B' => 'Harry',
'C' => 'British Army',
'D' => 'Eton College',
'E' => 'Cressida Bonas',
],
[
'A' => 'GB',
'B' => 'James',
'C' => 'British Army',
'D' => 'Millfield',
'E' => 'Unknown',
]
];
// What values are different
$result2 = array_diff_assoc($array2[0], $array2[1]);
print_r($result2);
// A Way to check numerically
$perfectMatch = 5;
$intersect = array_intersect_assoc($array1[0], $array1[1]);
$intersectCount = count($intersect);
if ($intersectCount != $perfectMatch) {
echo "<br> Not Every value matches.";
} else {
echo "<br> Perfect Match!";
}
To compare the full arrays $array1 and $array2 you can do:
<?php
// (With array code above)
$c1 = count($array1);
$c2 = count($array2);
if ($c1 != $c2) {
echo "<br>Array Children must be the same";
}
$result = [];
for ($i = 0; $i < $c1; $i++) {
$in_common = array_intersect($array1[$i], $array2[$i]);
$result[] = count($intersect);
}
print_r($result);
You can just use array_map(), assuming both arrays are of the same length:
$result = array_map(function($a, $b) {
return [$a == $b]; // create single element boolean array
}, $array1, $array2);
You can use either == or ===; the former (==) will yield true if both arrays have the same key and value pairs, whereas the latter (===) will only yield true if the keys of both arrays are also in the same order.
Some answers use the == operator; however that will not work if the arrays do not have the same key=>value matchings; Try this:
$results = array();
foreach ($array1 as $i => $subarray)
{
/* No need to proceed if subarray[i] does not exist in the second array */
if(!is_array($array2[$i]))
{
$results[$i] = false;
continue;
}
$results[$i] = (count(array_diff($array1[$i], $array2[$i])) == 0) ? true : false;
}
This solution is a bit slower than using the == comparison operator. However using the == will not work for a case like:
$array1 => array(1 => "John", 2 => "James");
$array2 => array(1 => "James", 2 => "John");
Here, the keys are not the same, but the values are duplicated. Solutions using == will return false when comparing these arrays.
$array1 == $array2 // False

Comparing Associative array and array

This is one array
Array ( [0] => 1 [1] => 2 )
The associative array is
Array ( [0] => Array ( [id_1] => 3 [id_2] => 1 ) [1] => Array ( [id_3] => 5 [id_4] => 3 ) )
I want to compare these arrays and get an array containing the values that are not present in the associative array
The result should be array(3) and array(5,3)
$array1 = array(1,2);
$array2 = array(
array(
'id_1' => 3,
'id_2' => 1
),
array(
'id_3' => 5,
'id_4' => 3,
)
);
I'm not sure if I understand the question, if you want to compare each array individually:
foreach($array2 as $subarray) {
var_dump(array_diff($subarray, $array1));
}
returns:
array
'id_1' => int 3
array
'id_3' => int 5
'id_4' => int 3
Otherwise if you don't want to loop through and flatten the array (using an array_flatten function from the php doc comments of array_values)
http://www.php.net/manual/en/function.array-values.php#97715
function array_flatten($a,$f=array()){
if(!$a||!is_array($a))return '';
foreach($a as $k=>$v){
if(is_array($v))$f=array_flatten($v,$f);
else $f[$k]=$v;
}
return $f;
}
var_dump(
array_unique(
array_diff(
array_flatten($array2), $array1
)
)
);
returns:
array
'id_1' => int 3
'id_3' => int 5
'id_4' is not shown because it doesn't have a unique value. You can remove the keys with array_values() or leave in 'id_4' by removing the array_unique() from the code.
something like this, maybe?
$array_a = array(1, 2);
$array_b = array(array(1, 3), array(3, 1));
$result = array();
foreach($array_b as $key => $sub_array_b){
foreach($sub_array_b as $sub_key => $value){
if(!in_array($value, $array_a) && !in_array($value, $result)) array_push($result, $value);
}
}
EDIT: I typed this before you edited your question. You can still modify the code above so that it creates a different array for each subarray in your associative array.

Categories