How to get difference between Associate arrays in PHP - php

I have an arrays like this
Array
(
[original_data] => Array
(
[0] => Array
(
[reference_id] => 122
[id] => 121
[reference_name] => Dinesh
)
[1] => Array
(
[reference_id] => 123
[id] => 120
[reference_name] => Dinesh Test
)
)
[edited_data] => Array
(
[0] => Array
(
[reference_id] => 123
[id] => 120
[reference_name] => Dinesh Test2
)
)
)
I want to get the difference between this original_data and edited_data arrays. How to do that? I tried using array_diff. But, It didn't work correctly.

You can get the difference =>
$result = ref_array_diff($requestedData['edited_data'], $requestedData['data']);
print_r($result);
function ref_array_diff($arraya, $arrayb) {
foreach ($arraya as $keya => $valuea) {
if (in_array($valuea, $arrayb)) {
unset($arraya[$keya]);
}
}
return $arraya;
}

If you use array_map on both original data and edited data to get an array of original_data id values and edited_data id values. You can then use array_diff with no problem. Using the resulting list of id's which are in one but not the other you can lookup the original value using the array mapped values index key on the original arrays.
I'm making the assumption here that your id key is a unique identifier for each value in the data arrays. If this isn't the case you'll need to do some nested loops to compare deep values

This should work.
<?php
// your data
$data = array (
'original_data' => array
('0' => array
(
'reference_id' => 122,
'id' => 121,
'reference_name' => 'Balasuresh,'
),
'1' => array
(
'reference_id' => 123,
'id' => 120,
'reference_name' => 'Balasuresh',
),
),
'edited_data' => array
('0' => array
(
'reference_id' => 123,
'id' => 120,
'reference_name' => 'Balasuresh Test',
),
)
) ;
// let's get our reference_ids
$originalData = array() ;
foreach($data['original_data'] as $entry) {
$originalData[$entry['reference_id']] = $entry ;
}
// let's compare our edited data to our original data
$editedData = array() ;
foreach($data['edited_data'] as $editedEntry) {
if (isset($originalData[$editedEntry['reference_id']])) {
// for readability
$compare = $originalData[$editedEntry['reference_id']] ;
foreach($editedEntry as $key=>$value) {
if ($compare[$key] != $value) {
$editedData[$editedEntry['reference_id']][$key] = $value ;
}
}
}
}
$editedData now contains your differences

These are multi-dimensional associative arrays, you can recursively do an array_diff_assoc like this:
you can check this code here https://3v4l.org/ovaQB:
function array_diff_assoc_recursive($array1, $array2)
{
foreach($array1 as $key => $value)
{
if(is_array($value))
{
if(!isset($array2[$key]))
{
$difference[$key] = $value;
}
elseif(!is_array($array2[$key]))
{
$difference[$key] = $value;
}
else
{
$new_diff = array_diff_assoc_recursive($value, $array2[$key]);
if($new_diff != FALSE)
{
$difference[$key] = $new_diff;
}
}
}
elseif(!isset($array2[$key]) || $array2[$key] != $value)
{
$difference[$key] = $value;
}
}
return !isset($difference) ? 0 : $difference;
}
$a=["original_data"=>[
[
'reference_id' => 122,
'id' => 121,
'reference_name' => 'Balasuresh'
],[
'reference_id' => 123,
'id' => 120,
'reference_name' => 'Balasuresh'
]
],
'edited_data' => [[
'reference_id' => 123,
'id' => 120,
'reference_name' => 'Balasuresh Test'
]]
];
print_r(array_diff_assoc_recursive($a['edited_data'], $a['original_data']));
output:
Array
(
[0] => Array
(
[reference_id] => 123
[id] => 120
[reference_name] => Balasuresh Test
)
)

Related

Create smart recursive function for multidimensional array which returns all arrays inside in one array

The main thing is multidimensional arrays can be random and I don't know exactly how many arrays inside in it. That why function should include recursion and checks does it have more array inside, example below can't do it without pre configuration. Appreciating any help
$arrays = array(
array(
'House' => 'Baratheon',
'Sigil' => 'A crowned stag',
'Motto' => 'Ours is the Fury',
),
array(
'Leader' => 'Eddard Stark',
'House' => 'Stark',
'Motto' => 'Winter is Coming',
'Sigil' => 'A grey direwolf'
),
array(
array('SomeArray' => 'You are cool'),
'House' => 'Lannister',
'Leader' => 'Tywin Lannister',
'Sigil' => 'A golden lion'
),
array(
'Q' => 'Z'
)
);
function next_element($array) {
foreach ($array as $some_type) {
if (is_array($some_type)) {
return true;
} else {
return false;
}
}
}
function check_in($inputs) {
foreach ($inputs as $position => $input) {
if (is_array($input) && next_element($input)) { // case with multidimentional array
check_in($input);
$check_in_result[] = "There are should be recursion!!!!!";
} else { // case with one simple array
$check_in_result[] = $input;
}
}
return $check_in_result;
}
Have tried with array_walk_recursive() but that function is working with all elements and returns as result one array with all keys and values. In this case it should be array(array1, array2, array3, array4) for next stage which is foreach loop.
As resutl it should be:
Array
(
[0] => Array
(
[House] => Baratheon
[Sigil] => A crowned stag
[Motto] => Ours is the Fury
)
[1] => Array
(
[Leader] => Eddard Stark
[House] => Stark
[Motto] => Winter is Coming
[Sigil] => A grey direwolf
)
[2] => Array
(
[SomeArray] => You are cool
)
[3] => Array
(
[House] => Lannister
[Leader] => Tywin Lannister
[Sigil] => A golden lion
)
[4] => Array
(
[Q] => Z
)
)
Try using a recursive function like this:
function parseMyArray($array) {
$result = [];
$row = [];
foreach($array as $key => $item) {
if (is_array($item)) {
$result = array_merge($result, parseMyArray($item));
} else {
$row[$key] = $item;
}
}
return !empty($row) ? array_merge($result, [$row]) : $result;
}
$result = parseMyArray($arrays);
print_r($result);
At each level of a function call, all scalar values with their keys are collected into one array as $row and merged with the $result of a nested function call.
fiddle

how to get array with unique values in laravel/php

I need to merge arrays into 1 array but what I need is to remove before the main data they b oth have in common (duplicated values i mean), I need only unique values when merged.
array formed from foreach.
public $arrayfields= [];
public $itemMap = [];
public function getRowMapping(array $row,$uniqueField,$moduleName)
{
$arrayData = [];
foreach ($this->columnMapping as $key => $value) {
$row = $this->moduleType($key,$value,$row,$moduleName);
}
$unique = $row[$uniqueField];
if(!isset($this->itemMap[$unique])){
$this->itemMap[$unique] = $row;
$this->itemMap[$unique][$unique]['items'] = [];
}
$this->itemMap[$unique]['items'][] = $row['items'];
return $row;
}
i changed little bit to my input
How can i do that?
so now the input will be like this
Array
(
[bill_type] => 1
[bill_number] => BIL-003
[order_number] => ON-003
[items] => Array
(
[track_inventory] => 0
[sku1] => sku1
[name] => Kidswear1
)
)
Array
(
[bill_type] => 1
[bill_number] => BIL-003
[order_number] => ON-003
[items] => Array
(
[track_inventory] => 0
[sku1] => sku2
[name] => Pant
)
)
Array
(
[bill_type] => 1
[bill_number] => BIL-002
[order_number] => ON-002
[items] => Array
(
[track_inventory] => 0
[sku1] => sku3
[name] => Pants
)
)
The final output I'm looking for is
Array
(
[BIL-003] => Array
(
[bill_type] => 1
[order_number] => ON-003
[items] => Array
(
[0] => Array(
[track_inventory] => 0
[sku1] => sku1
[name] => Kidswear1
)
[1] => Array
(
[track_inventory] => 0
[sku1] => sku2
[name] => Pant
)
)
[BIL-002] => Array
(
[bill_type] => 1
[order_number] => ON-002
[items] => Array
(
[0] => Array(
[track_inventory] => 0
[sku1] => sku3
[name] => pants
)
)
)~~~
I think there is no standard library function to accomplish this.
So here is the function that accomplishes this:
function merge($array1, $array2)
{
$arraymerged = [];
if (is_array($array1) && is_array($array2)) {
//collect the keys of two arrays
$keys = [];
foreach ($array1 as $key => $value) {
$keys[$key] = true;
}
foreach ($array2 as $key => $value) {
$keys[$key] = true;
}
//merge key values for each key
foreach ($keys as $key => $value) {
if (isset($array1[$key]) && isset($array2[$key])) {
if ($array1[$key] == $array2[$key]) {
$arraymerged[$key] = $array1[$key];
} else {
$arraymerged[$key] = [$array1[$key], $array2[$key]];
}
} else if (isset($array1[$key]))
$arraymerged[$key] = $array1[$key];
else
$arraymerged[$key] = $array2[$key];
}
return $arraymerged;
}
}
Here is my suggestion,
if the input is array, check my answer on this post Convert an associative array into an associative array which has a key with another associative array as its value in php
otherwise check below code.
bill_number as unique key and run foreach and append items array elements.
let me give you an example
$arr1 = [
"bill_type" => 1,
"bill_number" => 'BIL-003',
"items"=>[
0 => [
"name"=>"test"
]
]
];
$arr2 = [
"bill_type" => 1,
"bill_number" => 'BIL-003',
"items"=>[
0 => [
"name"=>"test_2"
]
]
];
$formattedArr = [];
//merge these arrays
$combinedArr = [];
$combinedArr[] = $arr1;
$combinedArr[] = $arr2;
foreach($combinedArr as $key=>$value){
$formattedArr[$value['bill_number']]["bill_type"] = $value["bill_type"];
$formattedArr[$value['bill_number']]["items"][] = $value["items"];
}
print_r($formattedArr);
I haven't tested this code, but i think this will be ans to your question.
<?php
$a1 = array(
"bill_type" => "1",
"bill_number" => "BIL-003",
"order_number" => "ON-003",
"items" => array(
"track_inventory" => "0",
"sku1" => "sku1",
"name" => "Kidswear1"
)
);
$a2 = array(
"bill_type" => "1",
"bill_number" => "BIL-003",
"order_number" => "ON-003",
"items" => array(
"track_inventory" => "0",
"sku1" => "sku2",
"name" => "Pant"
)
);
$result = function ($a1, $a2) {
$b1 = $a1['items'];
$b2 = $a2['items'];
$c1 = $a1;
$c2 = $a2;
unset($c1['items']);
unset($c2['items']);
if (count(array_diff($c1, $c2)) == 0) {
if (count(array_diff($b1, $b2)) != 0) {
$c1['items'] = [$b1, $b2];
} else {
$c1['items'] = $b1;
}
return $c1;
}else{
//you should complete this part by yourself, if first parts are not equal.
}
return $c1;
};
$r = $result($a1, $a2);
var_dump($r);
result:
(array) [4 elements]
bill_type: (string) "1"
bill_number: (string) "BIL-003"
order_number: (string) "ON-003"
items:
(array) [2 elements]
0:
(array) [3 elements]
track_inventory: (string) "0"
sku1: (string) "sku1"
name: (string) "Kidswear1"
1:
(array) [3 elements]
track_inventory: (string) "0"
sku1: (string) "sku2"
name: (string) "Pant"

How to change date format in multidimensional array and iterate all array with key

I have a multidimensional array with key and value and some key is empty also. Then I want to set a value for internal not empty array.
$oldArray = array("Lexus LS600" => array(),
"Toyota Alphard" => array(),
"Benz S550" => array(0 => array(
"card_no" => "G2FPCBS3",
"travel_date" => "2020-09-10"
"travel_time" => "16:15:00",
"car_id" => 12,
"return_time" => "17:25")),
"BMW X6" => array());
I had this array but I want to set return_time 00:00 all over array. I tried foreach loop but foreach is remove empty array but I want empty array also.
I want this type array:-
$newArray = array("Lexus LS600" => array(),
"Toyota Alphard" => array(),
"Benz S550" => array(0 => array(
"card_no" => "G2FPCBS3",
"travel_date" => "2020-09-10"
"travel_time" => "16:15:00",
"car_id" => 12,
"return_time" => "00:00")),
"BMW X6" => array());
Try this foreach again, I think it will solve your problem if I understood you correctly.
foreach ($arrays as $key => $values) {
if (is_array($values)) {
if (count($values)) {
foreach ($values as $index => $data) {
$arrays[$key][$index]['return_time'] = "00:00";
}
} else {
$arrays[$key] = $values;
}
}
}
It will change return_time to "00:00" and also retain the empty index to your array.
array_walk_recursive() is very suitable for this.
$oldArray = array("Lexus LS600" => array(),
"Toyota Alphard" => array(),
"Benz S550" => array(0 => array(
"card_no" => "G2FPCBS3",
"travel_date" => "2020-09-10",
"travel_time" => "16:15:00",
"car_id" => 12,
"return_time" => "17:25")),
"BMW X6" => array());
$keySearch = "return_time";
$replaceWith = "00:00";
array_walk_recursive(
$oldArray,
function(&$val,$key) use($keySearch,$replaceWith){
if($key == $keySearch) $val = $replaceWith;
}
);
var_export($oldArray);
Output:
array (
'Lexus LS600' =>
array (
),
'Toyota Alphard' =>
array (
),
'Benz S550' =>
array (
0 =>
array (
'card_no' => 'G2FPCBS3',
'travel_date' => '2020-09-10',
'travel_time' => '16:15:00',
'car_id' => 12,
'return_time' => '00:00',
),
),
'BMW X6' =>
array (
),
)
Use two foreach loops to traverse the limited-depth array and make all values modifiable by reference (& before the variable). In doing so, you don't need to create a separate array, just update the input array. It is SUPER easy to read and maintain.
Code: (Demo)
foreach ($array as &$cars) {
foreach ($cars as &$entry) {
if ($entry) {
$entry["return_time"] = "00:00";
}
}
}
var_export($array);
Output:
array (
'Lexus LS600' =>
array (
),
'Toyota Alphard' =>
array (
),
'Benz S550' =>
array (
0 =>
array (
'card_no' => 'G2FPCBS3',
'travel_date' => '2020-09-10',
'travel_time' => '16:15:00',
'car_id' => 12,
'return_time' => '00:00',
),
),
'BMW X6' =>
array (
),
)

Php string comparision in multidimensional array

I have two multidimensional array
Array
(
[0] => Array
(
[code] => 2079
[label] => Nike
)
[1] => Array
(
[code] => 1080
[label] => Adidas
)
)
Array
(
[0] => Array
(
[manufacturers_id] => 2753
[manufacturers_name] => Reebok
)
[1] => Array
(
[manufacturers_id] => 2526
[manufacturers_name] => Adidas
)
[2] => Array
(
[manufacturers_id] => 34
[manufacturers_name] => Nike
)
)
I want to do string matching of a key label of array 1 with key manufacturer_name of array 2. What is the best approach in multidimensional arrays ?
You could loop trough the arrays.
foreach ($multi_array1 as $value) {
foreach ($multi_array2 as $value2) {
If ($value[label] === $value2 [manufacturer_name])
{}
}
}
If you want to match by label and manufacturers_name, then I suggest you reindex your arrays by those fields:
$by_label = [];
foreach($first_array as $element) {
$by_label[$element['label']] = $element['code'];
}
$by_name = [];
foreach($second_array as $element) {
$by_label[$element['manufacturers_name']] = $element['manufacturers_id'];
}
foreach($by_label as $label => $code) {
print "Label is $label, code is $code, id is {$by_name[$label]}";
}
foreach($by_name as $name => $id) {
print "Name is $name, id is $id, label is {$by_label[$name]}";
}
Just use foreach to accomplish your desire result.
Array
$firstArr = array(
array("code" => 2079, "label" => 'Nike'),
array("code" => 1080, "label" => 'Adidas')
);
$secArr = array(
array("manufacturers_id" => 2753, "manufacturers_name" => 'Reebok'),
array("manufacturers_id" => 2526, "manufacturers_name" => 'Adidas'),
array("manufacturers_id" => 34, "manufacturers_name" => 'Nike')
);
Foreach Technique:
foreach($firstArr as $value){
if(in_array_sec($value['label'])){
echo $value['label'].' found in second array.';
}else{
echo $value['label'].' not found in second array.';
}
}
function in_array_sec($val_one){
global $secArr;
$flag = false;
foreach($secArr as $value){
if($value['manufacturers_name'] == $val_one){
$flag = true;
break;
}
else
$flag = false;
}
return $flag;
}
Result:
Nike found in second array.
Adidas found in second array.

PHP Counting inside an Array

I want to create a list where if its already in the array to add to the value +1.
Current Output
[1] => Array
(
[source] => 397
[value] => 1
)
[2] => Array
(
[source] => 397
[value] => 1
)
[3] => Array
(
[source] => 1314
[value] => 1
)
What I want to Achieve
[1] => Array
(
[source] => 397
[value] => 2
)
[2] => Array
(
[source] => 1314
[value] => 1
)
My current dulled down PHP
foreach ($submissions as $timefix) {
//Start countng
$data = array(
'source' => $timefix['parent']['id'],
'value' => '1'
);
$dataJson[] = $data;
}
print_r($dataJson);
Simply use an associated array:
$dataJson = array();
foreach ($submissions as $timefix) {
$id = $timefix['parent']['id'];
if (!isset($dataJson[$id])) {
$dataJson[$id] = array('source' => $id, 'value' => 1);
} else {
$dataJson[$id]['value']++;
}
}
$dataJson = array_values($dataJson); // reset the keys - you don't nessesarily need this
This is not exactly your desired output, as the array keys are not preserved, but if it suits you, you could use the item ID as the array key. This would simplify your code to the point of not needing to loop through the already available results:
foreach ($submissions as $timefix) {
$id = $timefix['parent']['id'];
if (array_key_exists($id, $dataJson)) {
$dataJson[$id]["value"]++;
} else {
$dataJson[$id] = [
"source" => $id,
"value" => 1
];
}
}
print_r($dataJson);
You should simplify this for yourself. Something like:
<?
$res = Array();
foreach ($original as $item) {
if (!isset($res[$item['source']])) $res[$item['source']] = $item['value'];
else $res[$item['source']] += $item['value'];
}
?>
After this, you will have array $res which will be something like:
Array(
[397] => 2,
[1314] => 1
)
Then, if you really need the format specified, you can use something like:
<?
$final = Array();
foreach ($res as $source=>$value) $final[] = Array(
'source' => $source,
'value' => $value
);
?>
This code will do the counting and produce a $new array as described in your example.
$data = array(
array('source' => 397, 'value' => 1),
array('source' => 397, 'value' => 1),
array('source' => 1314, 'value' => 1),
);
$new = array();
foreach ($data as $item)
{
$source = $item['source'];
if (isset($new[$source]))
$new[$source]['value'] += $item['value'];
else
$new[$source] = $item;
}
$new = array_values($new);
PHP has a function called array_count_values for that. May be you can use it
Example:
<?php
$array = array(1, "hello", 1, "world", "hello");
print_r(array_count_values($array));
?>
Output:
Array
(
[1] => 2
[hello] => 2
[world] => 1
)

Categories