Remove matching items from object - php

I have an object named $list that is formatted like the following
{"name":"cats","title":"Cats"},{"name":"dogs","title":"Dogs"},{"name":"rabbits","title":"Hares"}
I have a second object named $list2 formatted like the following:
{"title":"Cats","name":"cats"},{"title":"Dogs","name":"dogs"},{"title":"Pigs","name":"pigs"},{"title":"Funny","name":"funny"},{"title":"Pictures","name":"pictures"},{"title":"Finance","name":"finance"},{"title":"Cars","name":"cars"},
I would like to go through $list and check if it is in $list2. If the name item is in $list2's name items then I would like to remove it from $list. Expected result in this case would be
{"name":"rabbits","title":"Hares"}
I have tried a few different looping techniques but I cannot seem to get it to match up correctly.

What you're looking for is the built-in array_udiff() function. It finds the difference in the arrays with a function that you provide.
$result = array_udiff($list1, $list2, function($a, $b) {
return strcasecmp($a['name'], $b['name']);
});
So this would return all objects that are not in $list2 but are in $list1. I'm assuming the name determines uniqueness.

Related

How to sort 2D array of objects according to the object property

I've a 2D array like this
$myArray = [
0=>$Object,
1=>$Object,
2=>$Object,
3=>$Object,
//etc...
]
Each objects has properties and some of them have the same name for example. How can I sort my Array so that objects with the same name follow each other and only if there is no other objects with the same name property, I go to the next name ?
$myArray = [
//Objects with the first name
0=>$Object,
1=>$Object,
2=>$Object,
//Objects with the second name
3=>$Object,
4=>$Object,
//Objects with the third name
5=>$Object,
// etc.
]
The array is generated from database so it will never have the same size and the number of objects with a name can be one or more.
You can use usort() with anonymous function as below:
usort($dataArray, function($a, $b) {return strcmp($a->name, $b->name);});
or this:
function cmp($a, $b) {
return strcmp($a->name, $b->name);
}
usort($dataArray, "cmp");
This will sort your data objects with property name with their values.
Demo

Sorting array of objects by object variable, key being replaced

I have got an array of object instances, I need to sort these based on what a function within the object returns.
So basically my object has got 2 variables, the function will add them together, and then return the result, the list of objects need to be sorted based on this.
My sorting code:
function cmp($a, $b)
{
if ($a->calcPoints() == $b->calcPoints()) {
return 0;
}
return ($a->calcPoints() > $b->calcPoints()) ? -1 : 1;
}
usort($teamData, "cmp");
Without using the usort function I get the following when dumping my array:
Key: "Hull City FC" Value:
{"win":3,"draw":2,"loss":8,"goalFor":11,"goalConc":28} Key: "Leicester
City FC" Value: {"win":3,"draw":4,"loss":6,"goalFor":16,"goalConc":22}
Once I used the usort function, my keys are being replaced like so:
Key: 0 Value: {"win":10,"draw":1,"loss":2,"goalFor":29,"goalConc":10}
Key: 1 Value: {"win":9,"draw":3,"loss":1,"goalFor":29,"goalConc":12}
How can I stop this?
If you lookup usort() in the manual, you'll find:
Note: This function assigns new keys to the elements in array. It will remove any existing keys that may have been assigned, rather than
just reordering the keys.
uasort(), however, will: "Sort an array with a user-defined comparison function and maintain index association". Go ahead and try that, it should be what you're looking for.
You should use uasort function instead of usort. According to PHP documentation:
uasort — Sort an array with a user-defined comparison function and
maintain index association

array_merge is returning empty array when combining 2d arrays

I am attempting to use array_merge to merge two 2d arrays, but the result is always empty. There is no need to show you the whole php class, but I will paste the relevent code here. The problem is that when I use array_merge I get an empty array. I am calling my function called charts which in turn gets 2 arrays by calling 2 functions, then I wish to merge these arrays. The array functions do return a valid array, but when I merge them, I get nothing.
public function charts(){
$sales=$this->salesChart();
$expenses=$this->$this->expensesChart();
$result = array_merge($sales,$expenses);
print_r($result);
return $result;
}
private function salesChart(){
$salesArray = array(
array('2016-05', 14690),array('2016-06', 2785),array('2016-07', 14690),array('2016-08',23345),array('2016-09', 10345),array('2016-10',12456)
);
return $salesArray;
}
private function expensesChart(){
$expensesArray = array(
array('2016-05', 14690),array('2016-06', 2785),array('2016-07', 14690),array('2016-08',23345),array('2016-09', 10345),array('2016-10',12456)
);
return $expensesArray;
}
You have to change this line
$expenses=$this->$this->expensesChart();
for
$expenses=$this->expensesChart();
because I tested the array_merge and it works.
It is what it seems for the code you have provided.

Laravel's array_sort helper DESC e ASC

I want to sort a multidimensionl array by one or more keys using the Laravel helper array_sort.
array(
array('firstname_1','lastname_1'),
array('firstname_2','lastnmae_2')
)
I want to order it first by firstname and then by lastname.
I also want to do this in DESC or ASC order. How can I achieve this?
There are functions aivalable in the internet to do this but I would like to understand how to use the Laravel helper. The doc for array_sort (http://laravel.com/docs/helpers#arrays) I don't find comprehensive.
The array_sort() helper function is a very thin wrapper around the default Illuminate\Support\Collection::sortBy() method. Excluding comments, this is all that it does:
function array_sort($array, Closure $callback)
{
return \Illuminate\Support\Collection::make($array)->sortBy($callback)->all();
}
While handy, it is limiting in its sorting capabilities. Similarly, the Collection class will allow you to change sort direction, but not much else.
In my opinion, you have two options:
Skip a Laravel-only solution and use some normal PHP and array_multisort(). As #Jon commented, there's some great details in this SO question.
Use a combination of grouping and sorting in a Collection object to achieve the results you want.
I'd just stick with #1.
Just as an example how to sort by first name and then by last name with the sort helper of Laravel.
First define some more example data:
$array = array(
array('firstname_1','lastname_1'),
array('firstname_2','lastname_3'),
array('firstname_2','lastname_2'),
array('firstname_3','lastname_3'),
);
In our closure we want to sort by first name first, and then by last name. Laravel will sort by the returned values of the closure. So in your case the trick is to concatenate both strings:
$array = array_sort($array, function($value) {
return sprintf('%s,%s', $value[0], $value[1]);
});
Internally Laravel will now sort the contents of this intermediate array:
$intermediateArray = array(
'firstname_1,lastname_1',
'firstname_2,lastname_3',
'firstname_2,lastname_2',
'firstname_3,lastname_3',
);
This will result in an array which is sorted by first name and than by last name in ascending order.
To use descending order you need first sort the array and than reverse it:
$array = array_reverse(array_sort($array, function($value) {
return sprintf('%s,%s', $value[0], $value[1]);
}));

PHP Iterator Custom Sort Order (Laravel 4)

I have a "Post" object, accessed via the IOC container. Various errors tell me this object's type ends up as a "Collection", which implements several interfaces, including IteratorAggregate and ArrayAccess.
I want to display a user-defined group of posts according to a specific order, e.g.:
$desired=array("69","63","70");//these represent post id's
Just sorting an array in this manner seems complex, but I want to sort my collection. I have been researching various combinations of usort(), uksort(), Eloquent's sortBy(), array_multisort()... but the most obvious solutions result in orders like 3,2,1 or 1,2,3, not 2,1,3.
The closest I have gotten to this goal is to fetch the ones I want,
//BlogController
private function myposts($desired){
$posts=$this->post->whereIn('id',$desired)->get();
...
"convert" the Collection object to an array,
$posts=$posts->toArray();
and treat the array with a custom function: source
function sortArrayByArray($array,$orderArray) {
$ordered = array();
foreach($orderArray as $key) {
if(array_key_exists($key,$array)) {
$ordered[$key] = $array[$key];
unset($array[$key]);
}
}
return $ordered + $array;
}
$sorted=sortArrayByArray($array1,$desired);
I can then vardump the array in the correct order, but since it is now an array, I can't access the $posts object in my view. Can I convert the array back into a post object?
This whole approach feels wasteful anyway, converting to an array and back... is it? Is there a more straightforward way of sorting the contents of a "Collection"?
This is a little better, perhaps (a native php function):
array_multisort($desired,$posts,SORT_STRING);
//only works with string keys
//$desire=(1,2,3) will not work!
Again, this works for arrays, but attempting directly on the "posts" object fails...
Finally, I discovered using a Presenter: https://github.com/robclancy/presenter#array-usage which works in the view, after one of the above is completed in the controller:
#foreach($posts as $post)
<?php $post=new PostPresenter($post) ?>
{{View::make('site.post.article')->with(compact('post'))}}
#endforeach
This finally works, but it still feels like a long way to do it. Is there a better way to accomplish this task? Performance concerns or best practices with one method vs. another? Thanks in advance for anyone able to help.
You can use the Collections own sort method and pass in a callback. The callback compares every two values in your collection tells the sort method which one is "higher". The sort method then sorts them accordingly. If you want a specific value order you just create mapping and sort by that. For more info check uasort
$posts->sort(function($a, $b){
$desired=array("69" => 0,"63" => 1,"70" =>2);
if(!array_key_exists($a,$desired) || !array_key_exists($b,$desired) || $a == $b){
return 0
}
else{
return ($desired[$a] < $desired[$b]) ? -1 : 1;
}
});
Alternatively to #tim's answer, you can re-assign the sorted array to a new Collection object:
$postsArray = $this->posts->toArray();
// Do some sorting/processing, then:
$newCollection = new \Illuminate\Database\Eloquent\Collection( $postsArray );

Categories