Sort foreach loop result - php

I want to sort it by $distance base in foreach loop in my VIEWS.. so heres my code in Models
$db = $this->getDbo();
$query = $db->getQuery(true)
->select('*')
->from('#__load');
$db->setQuery($query);
$db->query();
$rows = $db->loadObjectList();
return $db->loadObjectList();
This is the code in my View where i want to sort it by distance
foreach ($this->items as $i => $item) {
$distance = $item->result1 * $item->result2
sort($distance)
}
echo $distance
result
3, 6, 2, 7, 8
i want to show like this
2, 3, 6, 7, 8

sort works on an array, and what you are doing is you are calling sort on every item in the array which wont work.
What you can do instead is do your foreach loop and then sort after:
$array = [];
foreach ($this->items as $i => $item) {
$distance = $item->result1 * $item->result2;
$array[] = $distance;
}
sort($array);
var_dump($array);
https://www.php.net/manual/en/function.sort.php

First Convert your result $this->items into (array)$this->items and then use one of the following function :
sort() - sort arrays in ascending order
rsort() - sort arrays in descending order
asort() - sort associative arrays in ascending order, according to the value
ksort() - sort associative arrays in ascending order, according to the key
arsort() - sort associative arrays in descending order, according to the value
krsort() - sort associative arrays in descending order, according to the key
and get sorted value.

There are a few things here that don't make sense to me, so I'll blindly try to refactor your scripts and put all of the processing in the model where it belongs (you shouldn't be manipulating data in the view).
Untested snippet:
$db = $this->getDbo();
$query = $db->getQuery(true)
->select('result1 * result2')
->from('#__load')
->orderBy(1);
$db->setQuery($query);
return $db->loadColumn();
Relevant pages to read:
How can a query multiply 2 cell for each row MySQL?
what is this order by 1?
https://docs.joomla.org/Selecting_data_using_JDatabase
I expect that your view will now receive the following sorted and indexed array:
$this->items = [2, 3, 6, 7, 8];
If you are a Joomla user, come join us at Joomla Stack Exchange. Have a browse of my answers to mysql tagged questions for explained examples and best practices.
If you are living in Brisvegas, come to our monthly Joomla User Group Meetup in West End (we aren't scary people). This is a place where you can leverage an IRL network of people that want to help you grow your skills and get your projects finished.

Related

Laravel: sorting collection by last name in single string

i'm trying to sort a collection, which consists of ids and full names, alphabetically by the last name.
the id comes from a parent class and the full name from the child.
I tried exploding the string and ordering according to the last name, but couldn't really get it to also reorder th IDs properly.
I tried both with sortBy while getting the collection and with usort after retrieving it
$testExaminers=TestExaminer::where('test_id',$request->testid)
->with('examiner')
->get()
->sortBy('examiner.name');
$result = array();
$num=0;
foreach($testExaminers as $testExaminer) {
$result[$num]['id'] = (int) $testExaminer->examiner_id;
$result[$num]['text'] = $testExaminer->examiner->name;
$num++;
}
echo json_encode(['examiners'=>$result]);
The code above works fine for sorting it by first name, but I need it to sort by last name.
user inputs test_id, which gives a list of "TestExaminers", each has a property "examiner_id" associated with a unique "examiner", which in turn has a name "firstname middlename lastname".
so it should look something like this
before sort
$result = [[1,'Alpha Z. Goodman'],[2,'Joe Bman'],[3,'ZZ Top'],[4,'Joe Aman']]
after sort
$result = [[4,'Joe Aman'],[2,'Joe Bman'],[1,'Alpha Z. Goodman'],[3,'ZZ Top']]
Thanks!
How about trying something like this?
$testExaminers = TestExaminer::where('test_id', $request->testid)
->with('examiner')
->get()
->map(function ($item, $key) {
$item->examiner->last_name = array_slice(explode(' ', $item->examiner->name), -1)[0];
return $item;
})
->sortBy('examiner.last_name');

Combine two queries into one and sort them

I am trying to display buildings and circuits in list (only 3 in total, sorted by the column "updated_at"). The problem is that they are not in the same table. I have a table circuits and a table buildings.
I tried to do this:
$buildings = Building::published()->limit(3)->get();
$circuits = Circuit::published()->limit(3)->get();
$merged = $buildings->merge($circuits);
$this->data['buildingsAndCircuits'] = $merged->all();
I get everything right when I'm doing my var_dump and I know how to access the data when I do a foreach. But that does not do what I want.
I would like to sort them (by updated_at) and have only three and not six.
Is there a way to do that?
I tried to make conditions like with the QueryBuilder on $merge but it does not work
$this->data['buildingsAndCircuits'] = $merged->orderBy('updated_at', 'DESC')->limit(3)->all();
thank you very much
Once you've called get on each query then the query is executed and the result is returned. orderBy will not longer work after that since what you have in $buildings, $circuits and $merged is a collection.
You can however do this:
$buildings = Building::published()->limit(3)->get();
$circuits = Circuit::published()->limit(3)->get();
$merged = $buildings->merge($circuits)->sortByDesc('updated_at');
$this->data['buildingsAndCircuits'] = $merged->all();
Check what else you can do on collections in the documentation

How can I sort this Collection using an array order?

How can I sort the $item type based on the order? This is what I currently have:
$order = ['AA', 'zl', 'Dr', 'co', 'og'];
$items->sort(
function ($a, $b) use ($order) {
return strcmp($b->type, $a->type) // how do I apply the order here?
?: strcmp($b->date, $a->date);
}
);
Basically it's a two column sort where it first sorts by type and then sorts by date. The type would be sorted using the array order rather than the typical alphabetical order.
You could compare the keys in $order corresponding to the type of each item.
return ($order[$b->type] - $order[$a->type])
?: strcmp($b->date, $a->date);
This should work if all of your items have types contained in $order. If not, you'll get undefined index errors which will mess up the sort. But since you haven't specified how items like that should be sorted in your question, I'm assuming that they all do.

Sort collection by custom order in Eloquent [duplicate]

This question already has answers here:
Sorting Laravel Collection via Array of ID's
(3 answers)
Closed last year.
I have an array of ID's as follows:
$ids = [5,6,0,1]
Using Eloquent I am able to search for these Id's using the ->whereIn('id', $ids) function. This as expected will return the results in the ascending order by Id, is there a way I can return the results on the order the array is in? alternatively whats the easiest way to convert the collection in the order of the $ids array?
If there's a specific order you'd like the records in, you'd have to use the Collection Methods:
To get your ID's in the very specific order you've specified, you can make use of the sortBy method as follows, where collection is your collection of models:
$ids = [ 5, 6, 0, 1];
$sorted = $collection->sortBy(function($model) use ($ids) {
return array_search($model->getKey(), $ids);
});
// [ 5, 6, 0, 1] // (desired order)
To randomize your collection you can make use of the shuffle method.
$collection = collect([1, 2, 3, 4, 5]);
$shuffled = $collection->shuffle();
$shuffled->all();
// [3, 2, 5, 1, 4] // (generated randomly)
See the Laravel Docs on shuffle and/or sortBy for more specific requirements.
If you don't really have a specific order in mind, you can use ->inRandomOrder() in version 5.2 and up, older versions would require the raw query using ->orderBy(DB::raw('RAND()')).
See answer to MySQL order by field in Eloquent. It is possible to order the data in your SQL query. Other answers here are suggesting you sort the data after you've already fetched it in "wrong" order.
Your code should look like this:
$ids = [5,6,0,1];
$collection = YourModel::whereIn('id', $ids)
->orderByRaw('FIELD (id, ' . implode(', ', $ids) . ') ASC')
->get();
You can pass a function into the sortBy method to perform complex sorting:
$ids = [5,6,0,1];
$collection = YourModel::whereIn('id', $ids)->sortBy(function($model) use ($ids) {
// Access your array order here and modify the sorting here
});

Preserve the initial order of array in Symfony2 Doctrine findBy()

I have an array ($newsList) of IDs with the following values: 4,2,1,3.
I'm trying to get some data from the database from entity:
$news=$this->getDoctrine()->getRepository('Bundle:News')->findBy(array('id' => $newsList));
$newsList array represents real IDs from the News entity.
But when I do:
foreach($news as $n){
$n->getId();
}
IDs are in order: 1,2,3,4.
How can I preserve the order from beginning in foreach?
You can't.
It's how it's returned from DB. If you won't specify ORDER BY clause in query, database will return rows as they are in storage, and this is usually the same as id ASC.
You should sort them on your own in PHP.
You can use usort and the spaceship operator:
$newsList = [4, 2, 1, 3];
$news = $this->getDoctrine()->getRepository(News::class)->findBy(['id' => $newsList]);
$order = array_flip($newsList);
usort($news, function($a, $b) use ($order) {
return $order[$a->getId()] <=> $order[$b->getId()];
});
// $news is now ordered by id 4,2,1,3
As you are doing a global query, you can just order your results by a given property, and a given sort order, so as pointed by the previous answer, you can't.
To have your results ordered exactly as the array you given, you can do this:
$newsList = [3, 1, 4, 2];
$newsRepo = $this->getDoctrine()->getRepository('Bundle:News');
foreach ($newsList as $id) {
$new = $newsRepo->findOneBy['id' => $id];
if ($new !== null) {
$news[] = $new;
}
}
Like this, your results are ordered exactly like $newsList, e.g:
foreach ($news as $n) {
print $n->getId();
}
// Output: 3 1 4 2
IMO the best solution is to use field function to get proper news order:
$ids = [4, 1, 2, 3];
$news = $this->getDoctrine()->getRepository('Bundle:News')->createQueryBuilder('n')
->select('n, field(n.id, :ids) as HIDDEN field')
->where("n.id IN (:ids)")
->setParameter('ids', $ids )
->orderBy(field)
->getQuery()
->getResult();
Note: this solution require custom field function that can be found here.
Try this:
$news = $this->getDoctrine()->getRepository('Bundle:News')->createQueryBuilder('n')
->where("n.id IN(:Ids)")
->setParameter('Ids', $newsList ) // $newsList = array(1,2,3,4,...)
->getQuery()
->getResult();
I don't know if you can actually get them sorted from the returning query results, but you can do either of these options:
Do a foreach loop and execute 'findByOne' for each result:
foreach($newsList as $id) {
$news[]=$this->getDoctrine()->getRepository('Bundle:News')->findBy(array('id' => $id));
}
Order the results of the query afterwards:
$news=$this->getDoctrine()->getRepository('Bundle:News')->findBy(array('id' => $newsList));
foreach($newsList as $id) {
$sorted_news[] = $news[$id];
}

Categories