Comparing Associative array and array - php

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.

Related

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;
},
[]
)
)
);

How do I return a key value by providing another key value in a multidimensional array in PHP?

Assume I have an array like the one below:
Array
(
[0] => Array
(
[town_id] => 1
[town_name] => ABC
[town_province_id] => 7
)
[1] => Array
(
[town_id] => 2
[town_name] => DEF
[town_province_id] => 4
)
[2] => Array
(
[town_id] => 3
[town_name] => GHI
[town_province_id] => 2
)
)
I want to provide value "DEF" in the above array and return value "2".
Please help me.
You can use in_array to get your result.
$input = 'DEF';
foreach($array as $key=>$value){
if(in_array($input,$value)){
$town_id = $value['town_id'];
}
}
print_r($town_id);
You can use array_search with array_column
$key = array_search('DEF', array_column($array, 'town_name'));
Example:
$data = array( array('town_id' => 1, 'town_name' => 'ABC'), array('town_id' => 2, 'town_name' => 'DEF') );
print_r($data);
$key = array_search('DEF', array_column($data, 'town_name'));
print_r($data[$key]['town_id']); // it will have 2
Use array_search and array_column
$key = array_search('DEF', array_column($your_arr, 'town_name'));
$your_arr[$key]['town_id']; // should return DEF
Note: array_column works from PHP 5 >= 5.5.0

Combine two arrays into a single array based on a common column value

I am trying to combine two arrays while respecting their shared value.
$array1 = array(
array("id" => "1","name"=>"John"),
array("id" => "2","name"=>"Peter"),
array("id" => "3","name"=>"Tom"),
array("id" => "12","name"=>"Astro")
);
$array2 = array(
array("id" => "1","second_name"=>"Lim"),
array("id" => "2","second_name"=>"Parker"),
array("id" => "3","second_name"=>"PHP")
);
My expected output:
$result = array(
array("id" => "1","name"=>"John","second_name"=>"Lim"),
array("id" => "2","name"=>"Peter","second_name"=>"Parker"),
array("id" => "3","name"=>"Tom","second_name"=>"PHP"),
array("id" => "12","name"=>"Astro")
);
I have made a try by
$arraycomb = array_unique(array_merge($array1,$array2), SORT_REGULAR);
My output is:
Array
(
[0] => Array
(
[id] => 1
[name] => John
)
[1] => Array
(
[id] => 2
[name] => Peter
)
[2] => Array
(
[id] => 3
[name] => Tom
)
[3] => Array
(
[id] => 12
[name] => Astro
)
[4] => Array
(
[id] => 1
[second_name] => Lim
)
[5] => Array
(
[id] => 2
[second_name] => Parker
)
[6] => Array
(
[id] => 3
[second_name] => PHP
)
)
How can I combine the key value inside same array? or how can I bring the expected output?
Note: I am trying for value instead of key ref: PHP Array Merge two Arrays on same key
Alternatively, you could use a foreach in this case then merge them if they share the same id key
With using reference &
foreach($array1 as &$value1) {
foreach ($array2 as $value2) {
if($value1['id'] == $value2['id']) {
$value1 = array_merge($value1, $value2);
}
}
}
echo '<pre>';
print_r($array1);
You can use array_map() for this. Try this -
function modifyArray($a, $b)
{
if (!empty($a) && !empty($b)) {
return array_merge($a, $b);
} else if (!empty($a) && empty($b)) {
return $a;
} else if (empty($a) && !empty($b)) {
return $b;
}
}
$new = array_map("modifyArray", $array1, $array2);
var_dump($new);
It will generate the new array will all the values in both arrays.if the first array's element is empty then the second array will be merged and vice-versa.
Assign temporary first level keys to your first array to aid in identifying rows. Then loop the second array and append the desired column value to the appropriate group. Re-index the array after looping with array_values().
Code: (Demo)
$result = array_column($array1, null, 'id');
foreach ($array2 as $row) {
$result[$row['id']]['second_name'] = $row['second_name'];
}
var_export(array_values($result));
This is a more direct approach than brute force scanning arrays with nested loops.
If all ids in the second array exist in the first array, then the following simpler line can be written inside the body of the foreach().
$result[$row['id']] += $row;

Merging two assosiative arrays in php?

I have two associative arrays.
array ( [apple]=>1 [banana]=>2 cocunet => 3)
and other array is
array ( [apple]=>2 [banana]=>3 cocunet => 4)
now i want to merge my array like that
array ( [apple]=>1,2 [banana]=>2,3 cocunet => 3,4)
There is no such array in PHP. The thing you want can only be done by creating multidimentional arrays.
$a1 = array( 'apple'=>1,'banana'=>2,'coconut'=> 3);
$a2 = array( 'apple'=>2,'banana'=>3,'coconut'=> 4);
echo "<pre>";
print_r(array_merge_recursive($a1,$a2));
echo "</pre>";
For this you can use the array_merge_recursive() function.
PHPFiddle: http://3v4l.org/5OCKI
If you want the result to be a string then this should work:
foreach( $array_1 as $fruit => $num) {
if(array_key_exists($fruit, $array_2)){ //check if key from array_1 exists in array_2
$final_array[] = array($fruit => $array_1[$fruit].','.$array_2[$fruit]); //concatenate values from shared key
}
}
print_r($final_array) will return:
Array
(
[0] => Array
(
[apple] => 1,2
)
[1] => Array
(
[banana] => 2,3
)
[2] => Array
(
[coconut] => 3,4
)
)
<?php
$array1 = array("apple" => 5, "banana" => 1);
$array2 = array("banana" => 4, "coconut" => 6);
print_r( array_merge_recursive( $array1, $array2 ) );
?>
Returns:
Array ( [apple] => 5 [banana] => Array ( [0] => 1 [1] => 4 ) [coconut] => 6 )
I only used two elements in each of the primary arrays to demonstrate the output prior to having any groups existing, i.e. non-array value.

How do you reindex an array in PHP but with indexes starting from 1?

I have the following array, which I would like to reindex so the keys are reversed (ideally starting at 1):
Current array (edit: the array actually looks like this):
Array (
[2] => Object
(
[title] => Section
[linked] => 1
)
[1] => Object
(
[title] => Sub-Section
[linked] => 1
)
[0] => Object
(
[title] => Sub-Sub-Section
[linked] =>
)
)
How it should be:
Array (
[1] => Object
(
[title] => Section
[linked] => 1
)
[2] => Object
(
[title] => Sub-Section
[linked] => 1
)
[3] => Object
(
[title] => Sub-Sub-Section
[linked] =>
)
)
If you want to re-index starting to zero, simply do the following:
$iZero = array_values($arr);
If you need it to start at one, then use the following:
$iOne = array_combine(range(1, count($arr)), array_values($arr));
Here are the manual pages for the functions used:
array_values()
array_combine()
range()
Why reindexing? Just add 1 to the index:
foreach ($array as $key => $val) {
echo $key + 1, '<br>';
}
Edit   After the question has been clarified: You could use the array_values to reset the index starting at 0. Then you could use the algorithm above if you just want printed elements to start at 1.
This will do what you want:
<?php
$array = array(2 => 'a', 1 => 'b', 0 => 'c');
array_unshift($array, false); // Add to the start of the array
$array = array_values($array); // Re-number
// Remove the first index so we start at 1
$array = array_slice($array, 1, count($array), true);
print_r($array); // Array ( [1] => a [2] => b [3] => c )
?>
You may want to consider why you want to use a 1-based array at all. Zero-based arrays (when using non-associative arrays) are pretty standard, and if you're wanting to output to a UI, most would handle the solution by just increasing the integer upon output to the UI.
Think about consistency—both in your application and in the code you work with—when thinking about 1-based indexers for arrays.
You can reindex an array so the new array starts with an index of 1 like this;
$arr = array(
'2' => 'red',
'1' => 'green',
'0' => 'blue',
);
$arr1 = array_values($arr); // Reindex the array starting from 0.
array_unshift($arr1, ''); // Prepend a dummy element to the start of the array.
unset($arr1[0]); // Kill the dummy element.
print_r($arr);
print_r($arr1);
The output from the above is;
Array
(
[2] => red
[1] => green
[0] => blue
)
Array
(
[1] => red
[2] => green
[3] => blue
)
Well, I would like to think that for whatever your end goal is, you wouldn't actually need to modify the array to be 1-based as opposed to 0-based, but could instead handle it at iteration time like Gumbo posted.
However, to answer your question, this function should convert any array into a 1-based version
function convertToOneBased( $arr )
{
return array_combine( range( 1, count( $arr ) ), array_values( $arr ) );
}
EDIT
Here's a more reusable/flexible function, should you desire it
$arr = array( 'a', 'b', 'c' );
echo '<pre>';
print_r( reIndexArray( $arr ) );
print_r( reIndexArray( $arr, 1 ) );
print_r( reIndexArray( $arr, 2 ) );
print_r( reIndexArray( $arr, 10 ) );
print_r( reIndexArray( $arr, -10 ) );
echo '</pre>';
function reIndexArray( $arr, $startAt=0 )
{
return ( 0 == $startAt )
? array_values( $arr )
: array_combine( range( $startAt, count( $arr ) + ( $startAt - 1 ) ), array_values( $arr ) );
}
A more elegant solution:
$list = array_combine(range(1, count($list)), array_values($list));
The fastest way I can think of
array_unshift($arr, null);
unset($arr[0]);
print_r($arr);
And if you just want to reindex the array(start at zero) and you have PHP +7.3 you can do it this way
array_unshift($arr);
I believe array_unshift is better than array_values as the former does not create a copy of the array.
Changelog
Version
Description
7.3.0
This function can now be called with only one parameter. Formerly, at least two parameters have been required.
-- https://www.php.net/manual/en/function.array-unshift.php#refsect1-function.array-unshift-changelog
$tmp = array();
foreach (array_values($array) as $key => $value) {
$tmp[$key+1] = $value;
}
$array = $tmp;
It feels like all of the array_combine() answers are all copying the same "mistake" (the unnecessary call of array_values()).
array_combine() ignores the keys of both parameters that it receives.
Code: (Demo)
$array = [
2 => (object)['title' => 'Section', 'linked' => 1],
1 => (object)['title' => 'Sub-Section', 'linked' => 1],
0 => (object)['title' => 'Sub-Sub-Section', 'linked' => null]
];
var_export(array_combine(range(1, count($array)), $array));
Output:
array (
1 =>
(object) array(
'title' => 'Section',
'linked' => 1,
),
2 =>
(object) array(
'title' => 'Sub-Section',
'linked' => 1,
),
3 =>
(object) array(
'title' => 'Sub-Sub-Section',
'linked' => NULL,
),
)
If you are not trying to reorder the array you can just do:
$array = array_reverse( $array );
and then call it once more to get it back to the same order:
$array = array_reverse( $array );
array_reverse() reindexes as it reverses. Someone else showed me this a long time ago. So I can't take credit for coming up with it. But it is very simple and fast.
The result is an array with indexed keys starting from 0. https://3v4l.org/iQgVh
array (
0 =>
(object) array(
'title' => 'Section',
'linked' => 1,
),
1 =>
(object) array(
'title' => 'Sub-Section',
'linked' => 1,
),
2 =>
(object) array(
'title' => 'Sub-Sub-Section',
'linked' => NULL,
),
)
Here's my own implementation. Keys in the input array will be renumbered with incrementing keys starting from $start_index.
function array_reindex($array, $start_index)
{
$array = array_values($array);
$zeros_array = array_fill(0, $start_index, null);
return array_slice(array_merge($zeros_array, $array), $start_index, null, true);
}

Categories