I'd like to merge two user objects (one is a duplicate). The problem is, one user object has some fields the other doesn't and vice versa. I'd like to array_merge all the key/value pairs except for the id. Is there anyway to do this?
Here is my code below. When I try to merge, the $second_user doesn't delete like I would like it to. If I comment out the merge block, it deletes duplicates properly without merging. However, when I comment it back in, there are still duplicates.
I think the issue is trying to use array_merge when id is an immutable field.
public function combine($first_user, $second_user)
{
// Always make sure $first_user is the "original" user that we're going merge.
if ($first_user->created_at > $second_user->created_at) {
$tmp = $second_user;
$second_user = $first_user;
$first_user = $tmp;
}
// Merge their data and save to the first user
$updated_user = array_merge(array_filter($second_user->toArray()), array_filter($first_user->toArray()));
$first_user->fill($updated_user)->save();
$second_user->delete();
}
Just unset the id after the merge:
$array = array_merge($arr1, $arr2);
unset($array['id']);
I'm not 100% sure if I understood correctly, but if you wan't to achieve the following:
use $first_user var as the "main" var for storing data
and preserve $first_user var data (including ID)
and add fields of $second_user to the $first_user while preserving existing $first_user data
If thats the case, instead of array_merge just use array + operator:
$arr1 = array_filter($first_user->toArray());
$arr2 = array_filter($second_user->toArray());
$updated_user = $arr1 + $arr2; // union
The + operator returns the right-hand array appended to the left-hand array; for keys that exist in both arrays, the elements from the left-hand array will be used, and the matching elements from the right-hand array will be ignored.
Related
I'm receiving this array of objects and need to iterate over it, but the problem is that I need to get the value of the next item when its iterating, to compare the value of the current object with the next one, and if it's a different value, split this array in two.
So, I was doing it with next() php function:
//looking for the next register in the array
$next = next($finances);
//first array if exist different values
$aiuaEd = [];
//second array if exist different values
$aiua = [];
foreach ($finances as $finance) {
if ($finance->cnpj <> $next->cnpj) {
$aiua[] = $finance;
} else {
$aiuaEd[] = $finance;
}
}
This code works fine at some point, but then I got this error:
Trying to get property 'cnpj' of non-object in
I don't know why sometimes works well and sometimes don't, debugging this variables, I found that if my array have 2 objects inside only, when I'm looping over it, the $next->cnpj variable came as empty, and sometimes don't.
Can someone help me with this?
I solved it with a different approach, instead of using php next(), I first loop over this array saving the cnpj's into an array.
$cnpjs = [];
foreach($finances as $finance){
$cnpj[] = $finance->cnpj;
}
Then I use array_unique() to group this 2 differents CNPJ's and sort() to get the correct keys order.
//grouping cnpjs as unique, should exist only 2 keys
$cnpj = array_unique($cnpj);
//sort array keys to get in order
sort($cnpj);
Then I iterate over my $finances array again, but now I'm counting if this $cnpj array has more than 2 positions, which means that I have to split this data in two differents arrays.
foreach($finances as $finance){
if(count($cnpj) > 1){
if($finance->cnpj == $cnpj[1]){
$aiua[] = $finance;
}else{
$aiuaEd[] = $finance;
}
}else{
$aiuaEd[] = $finance;
}
}
I'm pretty sure that this is not the best approach for that problem, or at least the most optimized one, so I'm open for new approach's suggestions!
Just posting how I solved my problem in case anyone having the same one.
Notice that this approach is only usable because I know that will not exist more than 2 different's CNPJ's in the array.
I'm trying to store the users's input via the method get in an array to store it and further process it without overwriting the initial get-value. But I dont know how.. do I have to store them in a database to do that? Or can I just push every input into an array?
I believe the following should work for you... This will take all the $_GETs that you supply and put them in a new array so you can modify them without affecting the original $_GET array.
if(is_array($_GET)){
$newArr = $_GET; // modify $newArr['postFieldName'] instead of $_GET['postFieldName'] to preserve original $_GET but have new array.
}
That solution there will dupe the $_GET array. $_GET is just an internal PHP array of data, as is $_POST. You could also loop through the GETs if you do not need ALL of the GETs in your new array... You would do this by setting up an accepted array of GETs so you only pull the ones you need (this should be done anyways, as randomly accepting GETs from a form can lead to some trouble if you are also using the GETs for database/sql functions or anything permission based).
if(is_array($_GET) && count($_GET) > 0){
$array = array();
$theseOnly = array("postName", "postName2");
foreach($_GET as $key => $value){
if(!isset($array[$key]) && in_array($key, $theseOnly)){ // only add to new array if they are in our $theseOnly array.
$array[$key] = $value;
}
}
print_r($array);
} else {
echo "No $_GET found.";
}
I would just add to what #Nerdi.org said.
Specifically the second part, instead of looping through the array you can use either array_intersect_key or array_diff_key
$theseOnly = array("postName", "postName2");
$get = array_intersect_key( $_GET, array_flip($theseOnly);
//Or
$get = array_diff_key( $_GET, array_flip($theseOnly);
array_intersect_key
array_intersect_key() returns an array containing all the entries of array1 which have keys that are present in all the arguments.
So this one returns only elements you put in $theseOnly
array_diff_key
Compares the keys from array1 against the keys from array2 and returns the difference. This function is like array_diff() except the comparison is done on the keys instead of the values.
So this one returns the opposite or only elements you don't put in $theseOnly
And
array_flip
array_flip() returns an array in flip order, i.e. keys from array become values and values from array become keys.
This just takes the array of names with no keys (it has numeric keys by default), and swaps the key and the value, so
$theseOnly = array_flip(array("postName", "postName2"));
//becomes
$theseOnly = array("postName"=>0, "postName2"=>1);
We need the keys this way so they match what's in the $_GET array. We could always write the array that way, but if your lazy like me then you can just flip it.
session_start();
if(!isset($_SESSION['TestArray'])) $_SESSION['TestArray'] = array();
if(is_array($_GET)){
$_SESSION['TestArray'][] = $_GET;
}
print_r($_SESSION['TestArray']);
Thanks everybody for helping! This worked for me!
I have an array and I want to sort it:
$ArrayStock = array(array("SIZE","L","XL","M"),("STOCK","12","3","2"));
How can I sort the array by "SIZE"?
Alternatively, I could use this array as a starting point:
$ArrayStock = array(array("L","XL","M"),("12","3","2"));
You could do it like this:
// Combine into one associative array
$combined = array_combine($ArrayStock[0], $ArrayStock[1]);
// Rebuild it in the correct order:
foreach(["SIZE", "S","M","L","XL","XXL"] as $size) {
if (isset($combined[$size])) $result[$size] = $combined[$size];
}
// Split associative array back to its original structure:
$ArrayStock = [array_keys($result), array_values($result)];
Note that this structure is not so practical in its use. I would in fact stick with the associative array.
There will be a few ways to skin this cat. All of my methods will produce the expected output...
First, let's do it without restructuring your array (Demo):
$order=["XS","S","M","L","XL","2XL","3XL"]; // declare appropriate size order
$ArrayStock=[["L","XL","M"],["12","3","2"]];
// Order the first subarray:
uasort($ArrayStock[0],function($a,$b)use($order){
return (array_search($a,$order)>array_search($b,$order)?1:-1); // any unidentifed sizes will go to the front
});
// Sync the second subarray with first subarray:
$ArrayStock[1]=array_replace($ArrayStock[0],$ArrayStock[1]);
// Optionally re-index the keys:
$ArrayStock[0]=array_values($ArrayStock[0]);
$ArrayStock[1]=array_values($ArrayStock[1]);
Next I'll show a few ways that you can manipulate a restructured array. There is absolutely nothing wrong with the way that trincot has written his. These are just alternatives that I've come up with...
I agree with trincot about using sizes as keys (because they will be unique) and stock counts as values. So the first process is to generate that new array structure:
$ArrayStock=[["L","XL","M"],["12","3","2"]];
#1 One-liner array_combine() approach:
$new_structure=array_combine($ArrayStock[0],$ArrayStock[1]);
// $new_structure = ['L'=>'12','XL'=>'3','M'=>'2']
#2 foreach() approach:
foreach($ArrayStock[0] as $i=>$size){
$new_structure[$size]=$ArrayStock[1][$i];
}
// $new_structure = ['L'=>'12','XL'=>'3','M'=>'2']
Now to sort the new array, you can use uksort() or a range of other array functions / loops with your predetermined order array:
$order=["XS","S","M","L","XL","2XL","3XL"]; // declare whatever appropriate sizes in order
#1 uksort() with array_search() approach:
uksort($new_structure,function($a,$b)use($order){
return (array_search($a,$order)>array_search($b,$order)?1:-1);
// any unidentified sizes will go to the front of the array
});
// keep in mind, this doesn't declare $result, it sorts $new_structure
#2 array_replace() with array_flip()-array_intersect()-array_keys() approach:
$result=array_replace( // replace values on matching keys
array_flip( // swap keys with values
array_intersect(
$order, // keep values from here
array_keys($new_structure) // that exist here
)
),
$new_structure); // use these elements for replace
// $result=['M'=>'2','L'=>'12','XL'=>'3'];
#3 foreach() with array_intersect()-array_keys() approach:
// generate & iterate ordered array
foreach(array_intersect($order,array_keys($new_structure)) as $v){
$result[$v]=$new_structure[$v]; // build properly sorted array
}
// $result=['M'=>'2','L'=>'12','XL'=>'3'];
Finally as trincot has shown, you can revert the sorted data back to the initial format with one more one-liner:
$ArrayStock=[array_keys($result),array_values($result)];
I need to remove a element from an associative array with an string structure.
Example:
$array = array(
"one"=>array("Hello", "world"),
"two"=>"Hi"
)
I want to create a function that removes the elements like this:
function removeElement($p) {
// With the information provided in $p something like this should happen
// unset($array["one"]["hello"])
}
removeElement("one.hello");
Your base array is associative, the inner array (key one) is not, its a indexed array, which you can not access via ["hello"] but rather [0].
You can remove the hello value by using the unset function, but the indexes will stay as they are:
$array = ['Hello', 'World']; // array(0: Hello, 1: World)
unset($array[0]); // Array is now array(1: World)
If you wish to keep unset and keep the array indexes in order, you can fetch the values using the array_values function after unset:
unset($array[0]);
$array = array_values($array); // array(0: World)
Or you could use array_splice.
When it comes to using a string as key for multidimensional array with a dot-separator I'd recommend taking a look at laravels Arr::forget method which does pretty much exactly what you are asking about.
This would be a static solution to your question, in any case, you need to use explode.
function removeElement($p, $array) {
$_p = explode('.', $p);
return unset($array[$_p[0]][$_p[1]]);
}
But bear in mind, this doesn't work if you have more in $p (like: foo.bar.quux)
How can I tell if array element, in foreach loop, has a key?
Some code:
function test($p_arr){
foreach ($p_arr as $key => $value){
// detect here if key 'came with the array' or not
}
}
$arr1['a'] = 10;
$arr2[] = 10;
$arr3[2] = 10;
test($arr1); // yes
test($arr2); // no
test($arr3); // yes
edit #1
I am aware that $arr2 also as an automated index-key. I need to know if it is automated or not.
edit #2
My use of it is simple.
In the function, I create a new array and use the $key as the new $key, if it was provided by the function call. or the $value as the new $key, if it was omitted in the function call.
I know that I can just force the use of key to each element, but in some parts of the code, the data structure itself is very dynamic* - and i'm trying to stay flexible as much as possible.
*code that create other code, that create ... and so on.
There is no difference between explicit keys and implicit keys generated via []. The [] doesn't mean "give this element no key", it means "use the next key for this element".
Every element has a key
$arr1['a'] = 10; // key is the string 'a'
$arr2[] = 10; // key is will be the integer zero
$arr3[2] = 10; // key is the integer 2
Edit
Perhaps it would be good to understand why you wish to know if the index is automated or not? It seems odd.
Every array created has to have a key, whether it's a integer or string as the key or index, without no index the PHP would have no way to interpret or even pull information from the array it's self.
$Var = array ("String","anotherstring","sdfhs","dlj");
the above array will automatically be generated with a numeric index starting from 0.
$Array = array();
$Array[] = "This is a string";
The above will push information into the array, as there has been no index or key specified. It will automatically be assigned with the closest numeric value to 0, which does not already exist in the array.
$Array = array();
$Array['key'] = "This is another string";
The above will push information into the array also, but as we have specified an index with a string representation rather an automatically assigned value.
So the answer to your question, if i'm reading this Correctly.
If your referring to check if the array values are specified by PHP/The Code prior to reading the array. There is no soundproof method, as everything would need to be assigned to the array before it has data. further more, if your only adding elements to the array with a string key, then yes. It is possible.
If your relying on automatically generated numeric values, or assigning your own numeric values. it's impossible to tell if PHP has assigned this automatically, or you have specified.