Compare multidimensional array with array of keys only - php

I have a multidimensional array that looks like this:
"fields" => {
"name": "John"
"lastname": "Doe"
}
"data" => {
"person": array:2 [
0 => {
"adress": "foo"
"phone": "bar"
},
1 => {
"adress": "foo1"
"phone": "bar1"
}
]
}
Now I want to check that in this multidimensional array the follow keys exist so my second array to compare looks like this:
[
'fields' => [
"name",
"lastname",
],
"data" => [
"person" => [
"adress",
"phone"
]
],
]
Now here's what I've tried to compare the keys of my second array with the first array:
$result = array_diff_key($firstArray, array_flip($secondArray));
But this gives me an
array_flip(): Can only flip STRING and INTEGER values!
So I need a way to recursively flip the array or maybe I am doing it a bit wrong

I have a multidimensional array that looks like this ...
This is not an array, whatever you've done it now is amorphous trash, not an array not an json object.
$result = array_diff_key($firstArray, array_flip($secondArray));
array_diff_key() finds differences - unique keys
array_flip() replaces keys with values in the array
So I need a way to recursively flip the array or maybe I am doing it a bit wrong
Don't flip arrays, stop searching differences if you want to find the same keys.
You need at least 2 arrays (or objects) to comparison. If you will have 2 (not nested) arrays use
array_intersect_key($array1,$array2);
For nested arrays... you have to get all the keys and then compare.

Related

Laravel array_diff attributes [duplicate]

This question already has answers here:
how to compare the values of 2 arrays with each other in php and output the differences [duplicate]
(2 answers)
Closed last year.
I'm trying to implement a RecordsActivity trait like in the Birdboard example on Laracasts. Here's Jeffrey's code updated for Laravel >=5.7:
/**
* Fetch the changes to the model.
*
* #return array|null
*/
protected function activityChanges()
{
if ($this->wasChanged()) {
// weirdness here, see below
dump(
$this->oldAttributes,
$this->getAttributes(),
array_diff($this->oldAttributes, $this->getAttributes())
);
return [
'before' => Arr::except(array_diff($this->oldAttributes, $this->getAttributes()), 'updated_at'),
'after' => Arr::except($this->getChanges(), 'updated_at')
];
}
}
The dump() above produces the below response during the test (without annotations). Nothing changes between the two arrays, and it's obvious that one row is different, but somehow array_diff is failing.
// $this->oldAttributes
array:14 [
"name" => "890 Gleichner Lights Suite 446"
"address" => "890 Gleichner Lights Suite 446"
"city" => "Mantetown"
"state" => "CT"
"postal_code" => "00627"
"active" => false
]
// $this->getAttributes()
array:14 [
"name" => "890 Gleichner Lights Suite 446"
"address" => "Changed"
"city" => "Mantetown"
"state" => "CT"
"postal_code" => "00627"
"active" => false
]
// array_diff($this->oldAttributes, $this->getAttributes())
[]
Check the array_diff
array_diff ( array $array1 , array $array2 [, array $... ] ) :array
Compares array1 against one or more other arrays and returns the values in array1 that are not present in any of the other arrays.
So if one field's value is set empty, change the order cannot work too, for example: set the "address" => "", then array_diff($this->getAttributes(), $this->oldAttributes) will return [] too.
array_diff_assoc ( array $array1 , array $array2 [, array $... ] ) : array
Compares array1 against array2 and returns the difference. Unlike array_diff() the array keys are also used in the comparison.
Use array_diff_assoc is better:
$changes = array_diff_assoc($this->oldAttributes(), $this->getAttributes);

Adding nested children inside parent and nesting should be equal to number of elements in an array

I have to generate a nested array of parent and children. Basically, I have a list as below.
$changeLog = array(
array("data1" => "value1"),
array("data2" => "value2"),
array("data3" => "value3")
)
For each value of $changeLog I have to add a nested child in an array. So for instance, I have 3 values in changeLog the expected result should be as follows:
$finalResult = array(
"parent1" => "value1",
"child" => array(
"parent2" => "value2",
"child" => array(
"parent3" => "value3",
"child" => array(
"parent4" => "value4"
)
)
)
)
So, in short, for each value (that is basically an array, I have to fetch some values from that array that will be used in nested child) in $changeLog a nested child will be added. I tried to do it using recursion and in for loop too. But I am completely lost how to proceed with it. Can someome give me a hint how we can achieve it?
I like to have a data structure as simple as possible.
Also working with big nested arrays is always complicated.
I would propose to change format of $finalResult variable to the following(using some kind of tree structure without multidimensional array):
$finalResult = [
"1" => "value1",
"1.2" => "value2",
"1.2.3" => "value3",
"1.2.3.4" => "value4"
];
In this case array key "1" is unique ID and path of the parent1.
Array key "1.2" is unique path of the parent2, "2" is ID from parent2.
Array key "1.2.3" is unique path of the parent3, "3" is ID from parent3.
Array key "1.2.3.4" is unique path of the parent4, "4" is ID from parent4.
and so on...
In this case you can simply access elements, you can sort array by keys.
And f.ex. array key "1.2.3.4" show you that it's parent4 with ID "4" and it a child of parents with IDs "1", "2" and "3"
In array key "1.2.3.4" the last number after last dot is unique ID, everything before the last dot show you IDs of all parents.

Unsetting element in array

I am trying to remove a key/value pair from an array but it does not seem to work. Basically, I make an API call which returns JSON. As such I do
$tempArray = json_decode($projects, true);
If I output $tempArray I see something like this
array:2 [
0 => array:9 [
"id" => 4
"name" => "Some Project Name"
"value" => "234"
"user_id" => "1"
"client_id" => "97"
"contact" => "Jane Berry"
]
1 => array:9 [
"id" => 3
"name" => "Another Project Name"
"value" => "6"
"user_id" => "1"
"client_id" => "97"
"contact" => "John Doe"
]
]
I essentially need to remove the value element so I do this
unset($tempArray['value']);
If I output $tempArray after the unset, it displays exactly the same as before, with the value element and value there.
What do I need to do to completely remove this from my array?
Thanks
unset will not look recursivly to sub-array to remove the key value. Only if you have at first level a key named value will be removed. In your array first level keys are: 0 and 1.
So to remove value from all sub-arrays you have to go throw all items from the array and unset it. You can do this with a simple foreach.
foreach($tempArray as $key => $data) {
unset($data['value']);
$tempArray[$key] = $data; //Overwrite old data with new with value unset.
}
Now you will not have value key in sub-array items.
As per my comment, you have no key called 'value' which is a top level key in your array. If you array looked like this:
$myArray = array(
"value" => "My Value to delete",
"anotherKey" => "hello world",
);
Then you could do unset($myArray['value']); and you would remove the key and value. In your case, the key you are looking for is nested under a numeric key [0] or [1]. You could reference these specifically like this:
unset($tempArray[0]['value']);
but what I imagine you are looking to achieve is to remove any trace of the key value from your array in which case you would be better off doing something like this:
foreach($tempArray as &$nestedArray){
unset($nestedArray['value']);
}
Note the & symbol before the $nestedArray. This means 'pass by value' and will actually update the $tempArray in a single line without the need for anything else.
Further Reading:
PHP Docs - Arrays
PHP Docs - Foreach loop
PHP Docs - Pass by reference

PHP Definition MultiDimensional Associative Arrays

I have 2 arrays with some sample data and I just want to confirm if I have the terminology correct:
Multidimensional Array:
$names = array([
"name" => "Bob",
"age" => 25,
"level" => 6],
["name" => "Joe",
"age" => 34,
"level" => 6]
);
Multidimensional Associative Array:
$names = array(
"Bob" => array(
"age" => 25,
"diploma" => "DAC",
"level" => 6),
"Joe" => array(
"age" => 34,
"diploma" => "DAC",
"level" => 6)
);
The second is Associative because of the index being the name rather than an index number and MultiDimensional because it has more than one entry.
I know it is not really a programming question requiring a code solution, I am just learning the terminology.
I add my two cents. All said by others is pretty correct, but:
The main difference from associative arrays and "simple" arrays. With "simple" arrays you can do something like this
for( $i = 0; $i < count( $array ) - 1; $i++ ) {
$element = $array[ $i ];
// Do something with $element
}
With associative arrays, you cannot do it and, if you want to traverse all the arrays you have to do something like this
foreach( $array as $key => $element ) {
// Do something with $element
}
This approach (the foreach) can be applied to the "simple" array too, while the first can be applied ONLY to "simple" array
Multidimensional array are simply arrays with AT LEAST one element that is an array, no matter the "type"
By the way, it's always think about arrays as associative arrays, always. It prevents you some very simple mistakes later on
Both arrays are multidimensional associative array.
But in second array you can get details of Bob or Joe by just using their name as key. For example to get details of Bob you can just call:
$names['Bob']
In first array you have to know the id or index of array to which Bob details were stored.

Split Multidimensional Array into Smaller Arrays

I have a multidimensional array that looks like this:
{
"groups": [
{
"__v": 0,
"_create_date": "2014-08-20T23:00:12.901Z",
"_id": "53f5287ca78473a969001827",
"_last_message_date": "2014-08-20T23:04:36.347Z",
"activity": 0,
"blocked_users": [],
"created_by": {
"_id": "53e84b0eba84943c6d0003f8",
"_last_modified": "2014-08-20T00:11:05.399Z",
"first_name": "Jegg",
"last_name": "V"
},
"curated": false,
"diversity": 0,
"featured": false,
"flagged": false,
"last_message": {
"text": "let's talk beo",
"created_by": {
"_id": "53e84b0eba84943c6d0003f8",
"first_name": "Jegg",
"last_name": "V"
},
"_id": "53f52984a78473a969001833",
"_create_date": "2014-08-20T23:04:36.347Z"
},
"member_count": 1,
"messages_count": 1,
"name": "Test",
"public": true,
"recency": 52182276.347,
"score": 52182276.347,
"tags": []
},
This structure repeats over 3000 times creating a very large multidimensional array. I think I can use array_chunk($array, 300) to break the array into smaller chunks. But I can't figure out how to access them exactly.
What I want to do is independently loop through the newly chunked arrays. So I'd like to end up with something like:
$array1 = {...}
$array2 = {...}
$array3 = {...}
$array4 = {...}
... and so on
THen I could loop through each of the newly created arrays, which are essentially smaller groups of the original array, but of 3000 arrays in one multidimensional array as I have in the first place, I end up with these smaller ones of 300 arrays each.
I hope this makes sense, I'm kinda out of my league. Help is always appreciated.
I think your array is in json format.
First decode it and then pass to array_chunk method.
array_chunk($input_array, 300));
then access them as $input_array[0][0], $input_array[0][1]....... $input_array[0][299], $input_array[1][0], $input_array[1][1].....
EDIT: oh, somehow I entirely misread the question. array_chunk is something worth looking into.
You could try using extract to fetch array values to the "global" variable namespace.
extract takes three arguments: the array you wish to extract, flags, and prefix if needed.
I'm not sure how non-associative arrays are extracted, but you could try
$full_array = array(
array( ... ),
array( ... ),
array( ... ),
array( ... ),
...
);
// EXTR_PREFIX_ALL prefixes all extracted keys with wanted prefix (the third param).
$extract_amount = extract( $full_array, EXTR_PREFIX_ALL, 'prefix' );
Now you should have the array extracted and available for use with variable names $prefix0, $prefix1, $prefix2 and so on.
I'm not sure how smart it is to extract an array with hundreds of available values.

Categories