Reputation: 45
I am struggling with understanding what array function would work best for my particular situation. There seems to be a vast amount of confusion from others as well as I have read several posts.
I have two arrays with different structures but both contain an ID field I would like to compare.
Array one is my footage array... it looks something like:
array(1) {
[0]=> array(5) {
["ID"]=> string(3) "172"
["Name"]=> string(26) "172_535A-New_Product-1.mp4"
["Projects_ID"]=> string(2) "25"
["FileName_Display"]=> string(18) "535A-New_Product-1"
["FileName_Real"]=> string(22) "172_535A-New_Product-1"}}
In this array ID is what I want to compare. The other array has a lot more information and is thus structured completely different BUT it also has this same ID listed as Footage_ID. It looks something like:
array(1) {
[0]=> array(16) {
["ID"]=> string(3) "168"
["Unique_Array_ID"]=> string(1) "0"
["HTML_ID"]=> string(15) "Item_0_0_34_A_0"
["HTML_Selector"]=> string(10) "0_0_34_A_0"
["Frame_Selector"]=> string(8) "0_0_34_A"
["FootageArrayKey"]=> string(1) "0"
["Timeline"]=> string(1) "0"
["Tab"]=> string(1) "0"
["inPoint"]=> string(12) "5.7919480000"
["outPoint"]=> string(13) "43.2125420000"
["Duration"]=> string(13) "45.1200000000"
["Section"]=> string(1) "1"
["Green_Screen"]=> string(1) "1"
["Place_in_Timeline"]=> string(1) "0"
["Footage_ID"]=> string(3) "172"
["Projects_ID"]=> string(2) "25"
}}
With these two the Footage_ID in array #2 (172) matches the ID in array #1 (172). Therefore I do not need the entry from array #1. I am looking for only IDs not listed in array #2. This would be my return array.
First, since they are multidimensional I am a bit lost on comparing them. Are there any built in functions for this like array_diff? As far as I know array_diff is only for one dimensional array comparisons. The fact that the arrays are different structures may mean little but to me it also seems like it could be an issue for certain functions.
The function I seem to need would accept three values($array1, $array2, $key_to_compare_by). Then it would return the entries(arrays) from array1 where the $key_to_compare is not found. I have not seen this situation in particular talked about yet and was wondering if anyone has advice on how to accomplish this.
I see people talking about filtering, mapping, and other functions but there are so many different approaches and none seem to be exactly what I am facing currently. I giant part of this misunderstanding is that I DO NEED TO learn more about filtering, etc. Any advice on this problem would be helpful. Thanks!
Upvotes: 2
Views: 1026
Reputation: 47874
This question is simply solved by using array_column()
and array_diff()
because you are only comparing one "column" of values from each array.
Simplified Input and Code: (Demo)
$footage = [
["ID" => "172"],
["ID" => "174"],
["ID" => "176"],
["ID" => "178"],
["ID" => "180"]
];
$array2 = [
["Footage_ID" => "172"],
["Footage_ID" => "173"],
["Footage_ID" => "174"],
["Footage_ID" => "175"],
["Footage_ID" => "176"]
];
var_export(
array_diff(
array_column($footage, "ID"),
array_column($array2, "Footage_ID")
)
);
Output ($footage ID's that are not found in $array2's Footage_ID values):
array (
3 => '178',
4 => '180',
)
*note, you can choose to preserve the keys as in the above output, or you can call array_values()
on the result array to re-index the keys.
Also be aware that on large data sets you will notice a drag in performance due to making value-based comparisons. Functions that make value-based comparisons are array_diff()
, array_search()
, in_array()
, and others -- these potentially iterate ALL elements in the haystack array. Functions that make value-based comparisons do not perform as well as key-based comparisons in php. To enjoy the performance of array_diff_key()
, you will need to prepare the inputs in a slightly different fashion -- with temporary first level keys. This what I'd probably use:
Code: (Demo)
var_export(
array_diff_key(
array_column($footage, null, "ID"),
array_column($array2, null, "Footage_ID")
)
);
You could also use array_udiff()
and avoid the preparation of the new keys: (Demo)
var_export(
array_udiff(
$footage,
$array2,
fn($a, $b) => ($a['Footage_ID'] ?? $a['ID']) <=> ($b['Footage_ID'] ?? $b['ID'])
)
);
Upvotes: 1
Reputation: 1691
You can try this:
$secondArray
: Let's suppose is the array with the big data (array #2) of yours.
$arr1
: Let's suppose is the array with the small data (array #1) of yours.
foreach($arr1 as $k=>$v){
$key = array_search($v['ID'], array_column($secondArray, 'Footage_ID')); //if not found in second array, it will return false
if($key === false){
$filter_array[] = $v;
}
}
echo "<pre>12";print_r($filter_array);
Upvotes: 0
Reputation: 1672
The below uses a custom function.
Ok, i created 2 arrays :
$mBigArray
: Let's suppose is the array with the big data (array #2) of yours.
$mSmallArray
: Let's suppose is the array with the small data (array #1) of yours.
We just need a valid "ID" and "Footage_ID", the rest could be anything - dummy data.
$mBigArray = array(
array(
"id" => 1,
"dummyData123" => "dummy",
"dummyData5" => "dummy",
"dummyData1" => "dummy",
"dummyData494" => "dummy",
"dummyData5" => "dummy",
"dummyData3" => "dummy",
"dummyData6" => "dummy",
),
array(
"id" => 15123,
"dummyData123" => "dummy",
"dummyData5" => "dummy",
"dummyData1" => "dummy",
"dummyData494" => "dummy",
"dummyData5" => "dummy",
"dummyData3" => "dummy",
"dummyData6" => "dummy",
),
array(
"id" => 123,
"dummyData123" => "dummy",
"dummyData5" => "dummy",
"dummyData1" => "dummy",
"dummyData494" => "dummy",
"dummyData5" => "dummy",
"dummyData3" => "dummy",
"dummyData6" => "dummy",
),
);
$mSmallArray = array(
array(
"Footage_ID" => 1,
"dummyData5" => "dummy",
),
array(
"Footage_ID" => 123,
"dummyData5" => "dummy",
),
array(
"Footage_ID" => 0,
"dummyData5" => "dummy",
),
);
function findElementsThatDontExistFromArrayInArray($mFirstArray, $mSecondArray, $keyToCompareFirstArray, $keyToCompareSecondArray){
$mFinalArray = null; // Initialize
foreach($mFirstArray as $firstArrayCurrent){
$doesExist = false; // Initialize
foreach($mSecondArray as $secondArrayCurrent){
// Loop through all the elements and if element with the same id - footage_id exist then change the boolean.
if($firstArrayCurrent[$keyToCompareFirstArray] == $secondArrayCurrent[$keyToCompareSecondArray])
$doesExist = true;
}
if(!$doesExist) // If $doesExist is false, that means it was not found. Add that element to a final array.
$mFinalArray[] = $firstArrayCurrent;
}
return $mFinalArray; // Return it
}
$mFinalArray = findElementsThatDontExistFromArrayInArray($mSmallArray, $mBigArray, "Footage_ID", "id");
print_r($mFinalArray);
Output :
Array
(
[0] => Array
(
[Footage_ID] => 0
[dummyData5] => dummy
)
)
The object (with "Footage_ID" = 0) in $mSmallArray
doesn't exist in $mBigArray
(by comparing "id" and "Footage_ID") so it's returned to the final array.
Upvotes: 1
Reputation: 20250
If I understand the question correctly you want to return entries from the first array if the ID
doesn't exist as a Footage_ID
in the second array.
If that's the case you can use array_filter()
to check if each ID
from the first array exists in the array of Footage_ID
's from the second, and if it doesn't, return the current array:
$o = array_filter($array1, function($a1) use ($array2) {
return ! in_array($a1['ID'], array_column($array2, 'Footage_ID'));
});
Upvotes: 2