Jump to content

Sort results by closest value


3fingers
 Share

Recommended Posts

Hey all, I'm facing a problem way over my knowledge right now. Big problem and tight deadline :(

Basically is this:

$percentuale = 20; // percentace

if ($input->get->lunghezze) {
    $lunghezza = $sanitizer->selectorValue($input->get->lunghezze);
    $input->whitelist->lunghezze = $lunghezza;
    $tolleranza = ($percentuale / 100) * $lunghezza; // calculating the tolerance
    $val_up = floor($lunghezza + $tolleranza); // tolerance up
    $val_down = floor($lunghezza - $tolleranza); // tolerance down
    $selector .= "variante_prodotto.lunghezza=$lunghezza, ";
    $tolerance .= "variante_prodotto.lunghezza>=$val_down, ";
    $tolerance .= "variante_prodotto.lunghezza<=$val_up, ";
}
    $tolerance .= "template=prodotto_alimentare, sort=variante_prodotto.lunghezza";
      /* I want to sort the result from the closest to $lunghezza,
      but now they are sorted by the smallest to the greatest. */
    $matches = $pages->find($selector);
    $with_tolerance = $pages->find($tolerance);
    $insieme = $pages->find("id=$matches|$with_tolerance");
      
    foreach($insieme as $product) {
    //etc...
      }  

I'm outputting a series of product which has a particular length ($lunghezza) and also other products which are contained inside a particular tolerance ($with_tolerance).

How can i sort the results ($insieme) from the closest to $lunghezza onwards? Right now they are sorted by the smallest to the greatest.

Hope to have some feedback from you. Thanks!

Link to comment
Share on other sites

5 hours ago, 3fingers said:

How can i sort the results ($insieme) from the closest to $lunghezza onwards?

I don't think it will be possible to achieve this sort via SQL in the $pages->find() selector - you'll have to do it via PHP in memory, so hopefully you don't have too many results.

I don't know what sort of field variante_prodotto is so you may need to adapt this if it holds multiple values but here is the general idea:

foreach($insieme as $product) {
	// Here you might need to cast $product.variante_prodotto.lunghezza and $lunghezza to int or float as appropriate
	// Get difference as an absolute value as store as a custom property on $product
	$product->difference = abs($product.variante_prodotto.lunghezza - $lunghezza);
}
// Sort by custom property
$insieme->sort('difference');
// Now output your results
foreach($insieme as $product) {
	// ...
}

 

Link to comment
Share on other sites

Thanks @Robin S, I'm trying to get my head around it.
 

if ($input->get->lunghezze) {
    $lunghezza = $sanitizer->selectorValue($input->get->lunghezze);
    $input->whitelist->lunghezze = $lunghezza;
    $tolleranza = ($percentuale / 100) * $lunghezza;
    $val_up = floor($lunghezza + $tolleranza);
	$val_down = floor($lunghezza - $tolleranza);
	
    //SORT DELTA UP
	$lun_unsorted_up = $pages->find("variante_prodotto.lunghezza>=$lunghezza,variante_prodotto.lunghezza<=$val_up");
	foreach($lun_unsorted_up as $lun){
		$lun->delta = abs($lun->variante_prodotto[0]->lunghezza - $lunghezza);
	}
	$lun_sorted_up = $lun_unsorted_up->sort('delta');

    //SORT DELTA DOWN
	$lun_unsorted_down = $pages->find("variante_prodotto.lunghezza<=$lunghezza,variante_prodotto.lunghezza>=$val_down");
	foreach($lun_unsorted_down as $lun){
		$lun->delta = abs($lun->variante_prodotto[0]->lunghezza - $lunghezza);
	}
	$lun_sorted_down = $lun_unsorted_down->sort('delta');	
}

I have more input->get variables, and I'm applying the same concept. At a point in time I "join" all the array I get like this:

$insieme = $pages->find("id=$lun_sorted_up|$lun_sorted_down"); // and so on...

All good...but, if i put a "limit=20" to the selector (for pagination):

$insieme = $pages->find("id=$matches|$lun_sorted_up|$lun_sorted_down, limit=20");

The sorting order is completely gone! Why?

Link to comment
Share on other sites

Two problems...

1. As soon as you do this...

5 minutes ago, 3fingers said:

$insieme = $pages->find("id=$lun_sorted_up|$lun_sorted_down");

...you are going to lose any sorting that has been applied those PageArrays. Using $pages->find() and matching by ID doesn't preserve the order that the IDs are supplied in. Aside: $pages->getByID() does preserve the order of supplied IDs but you can't set a limit for pagination so it won't help you here.

2.

7 minutes ago, 3fingers said:

if i put a "limit=20" to the selector (for pagination)

You can't use pagination in the normal sense with this kind of sorting. Normally you use pagination for performance reasons, to avoid loading the entire result set into memory, but in this case you need the entire result set in memory so you can foreach over them to set the custom sort. That's why I said that hopefully you don't have too many results. If you have thousands of results you probably can't use this technique. If you want pagination for some other reason besides performance then you could look at something like saving the sorted PageArray to $session and then getting slices of that PageArray on each numbered results page. This post will get you started on that (substitute the sorted PageArray for images in that example):

 

Link to comment
Share on other sites

Hi,

I'm not so good in PHP ...

In a website I want to sort result using foreach, this is the code:

$profi = $pages->get("/professionisti/")->children('limit=4, sort=date'); 

My question is: if I want to change the order, from the latest to the oldest or from the oldest .. what I have to write?

Thanks a lot


 

Link to comment
Share on other sites

  • 3 months later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...