1

I have an array of StdClass Objects and want to return the "partner_code" with the minimum value for key "price". So for this example I would like to return partner_code "AC" as it is the partner with the lowest price. I tried using array_reduce, but I'm not sure what I'm doing wrong. Any help would be appreciated. Please note I am not looking to SORT this array. I just want to move the subarray containing AC (because it hold the lowest price) to the top - not sorting everything by price

Input Array:

Array
    (
    [0] => stdClass Object
        (
            [name] => Budget
            [partner_code] => BU
            [price] => 365.36
            [tier] => 1
        )

    [1] => stdClass Object
        (
            [name] => Avis
            [partner_code] => AV
            [price] => 449.71
            [tier] => 1
        )

    [2] => stdClass Object
        (
            [name] => E-Z
            [partner_code] => EZ
            [price] => 270.56
            [tier] => 2
        )

    [3] => stdClass Object
        (
            [name] => Sixt
            [partner_code] => SX
            [price] => 280.52
            [tier] => 2
        )

    [4] => stdClass Object
        (
            [name] => Alamo
            [partner_code] => AL
            [price] => 345.13
            [tier] => 2
        )

    [5] => stdClass Object
        (
            [name] => Advantage
            [partner_code] => AD
            [price] => 357.61
            [tier] => 2
        )

    [6] => stdClass Object
        (
            [name] => Enterprise
            [partner_code] => ET
            [price] => 364.46
            [tier] => 2
        )

    [7] => stdClass Object
        (
            [name] => ACE
            [partner_code] => AC
            [price] => 186.53
            [tier] => 3
        )

    [8] => stdClass Object
        (
            [name] => Fox
            [partner_code] => FX
            [price] => 265.25
            [tier] => 3
        )

    [9] => stdClass Object
        (
            [name] => Payless
            [partner_code] => ZA
            [price] => 380.47
            [tier] => 3
        )

    [10] => stdClass Object
        (
            [name] => Dollar
            [partner_code] => ZR
            [price] => 385.99
            [tier] => 3
        )

    [11] => stdClass Object
        (
            [name] => Thrifty
            [partner_code] => ZT
            [price] => 385.99
            [tier] => 3
        )

    [12] => stdClass Object
        (
            [name] => Silvercar
            [partner_code] => SC
            [price] => 424.10
            [tier] => 3
        )

    [13] => stdClass Object
        (
            [name] => National
            [partner_code] => NA
            [price] => 448.82
            [tier] => 3
        )

    [14] => stdClass Object
        (
            [name] => Hertz
            [partner_code] => HZ
            [price] => 487.33
            [tier] => 3
        )
    )

Code:

 array_reduce($this->results->companies, function($a,$b) {
        echo "Prices: " . $a->price . "<br>";
        return $a->price < $b->price ? (string)$a->partner_code : (string)$b->partner_code;
 });
4
  • I would just sort the array by price and then get the first or last element based on the sort direction, eg usort($this->results->companies, function($a, $b) { return $a->price - $b->price; }); $pc = $this->results->companies[0]->partner_code; Commented Sep 1, 2017 at 5:08
  • 1
    Try this one eval.in/853582 Commented Sep 1, 2017 at 5:17
  • "Please note I am not looking to SORT this array" <- it seems you are. How else would you determine the first entry by price? Commented Sep 1, 2017 at 5:37
  • Sorry let me clarify - I'd the following sort "AC" (lowest price), "BU", "AV", "EZ", SX"...so really it's just moving only AC with the lowest price to the top - not sorting everything by price Commented Sep 1, 2017 at 5:42

3 Answers 3

1
usort($array, function($a, $b) {
        return ($a->price - $b->price) ;
});

echo $array[0]->partner_code;
Sign up to request clarification or add additional context in comments.

3 Comments

Numeric sort functions are much easier if you just return "comparableA - comparableB"
Or $comparableA <=> $comparableB
@Scopey nice (needs PHP 7 though). Hardly worth it for numeric operations though. A simple subtraction would surely be computationally cheaper
0

If you really don't want to sort the array but instead use array_reduce, do so by reducing the array to one of its elements. Then you can get the partner_code property for that element.

For example

array_reduce($this->results->companies, function($lowest, $company) {
    // $lowest will be null on the first iteration
    return $lowest === null || $company->price < $lowest->price ?
        $company : $lowest;
})->partner_code;

2 Comments

Thanks Phil. If I wanted to return the position that the lowest price is in, how can I do that using the array_reduce function here? So for this example, position "7".
@MichaelAlterio You could use something like array_search to find the index of the element in the original array but now you're changing the requirements of your question. What is it exactly that you're trying to do?
0

This method will not sort the entire array. It will pull out the subarray with the lowest price and set it as the first element. I could have nested some of the functions to make it more compact (1-liner), but that would have damaged readability.

Code: (Demo)

$results=[
    (object)["name"=>"Budget","partner_code"=>"BU","price"=>"365.36","tier"=>"1"],
    (object)["name"=>"Avis","partner_code"=>"AV","price"=>"449.71","tier"=>"1"],
    (object)["name"=>"E-Z","partner_code"=>"EZ","price"=>"270.56","tier"=>"2"],
    (object)["name"=>"Sixt","partner_code"=>"SX","price"=>"280.52","tier"=>"2"],
    (object)["name"=>"Alamo","partner_code"=>"AL","price"=>"345.13","tier"=>"2"],
    (object)["name"=>"Advantage","partner_code"=>"AD","price"=>"357.61","tier"=>"2"],
    (object)["name"=>"Enterprise","partner_code"=>"ET","price"=>"364.46","tier"=>"2"],
    (object)["name"=>"ACE","partner_code"=>"AC","price"=>"186.53","tier"=>"3"],
    (object)["name"=>"Fox","partner_code"=>"FX","price"=>"265.25","tier"=>"3"],
    (object)["name"=>"Payless","partner_code"=>"ZA","price"=>"380.47","tier"=>"3"],
    (object)["name"=>"Dollar","partner_code"=>"ZR","price"=>"385.99","tier"=>"3"],
    (object)["name"=>"Thrifty","partner_code"=>"ZT","price"=>"385.99","tier"=>"3"],
    (object)["name"=>"Silvercar","partner_code"=>"SC","price"=>"424.10","tier"=>"3"],
    (object)["name"=>"National","partner_code"=>"NA","price"=>"448.82","tier"=>"3"],
    (object)["name"=>"Hertz","partner_code"=>"HZ","price"=>"487.33","tier"=>"3"]
];
$min=min(array_column($results,'price'));  // find the minimum value
$index=array_search($min,array_column($results,'price'));  // find the index of the subarray containing min value
$pulled=array_splice($results,$index,1);  // extract the subarray and preserve it as $pulled
$new_results=array_merge($pulled,$results);  // set $pulled as first element
var_export($new_results);

...okay, okay, here's the one-liner: var_export(array_merge(array_splice($results,array_search(min(array_column($results,'price')),array_column($results,'price')),1),$results));

Output:

array (
  0 => 
  stdClass::__set_state(array(
     'name' => 'ACE',
     'partner_code' => 'AC',
     'price' => '186.53',
     'tier' => '3',
  )),
  1 => 
  stdClass::__set_state(array(
     'name' => 'Budget',
     'partner_code' => 'BU',
     'price' => '365.36',
     'tier' => '1',
  )),
  2 => 
  stdClass::__set_state(array(
     'name' => 'Avis',
     'partner_code' => 'AV',
     'price' => '449.71',
     'tier' => '1',
  )),
  3 => 
  stdClass::__set_state(array(
     'name' => 'E-Z',
     'partner_code' => 'EZ',
     'price' => '270.56',
     'tier' => '2',
  )),
  4 => 
  stdClass::__set_state(array(
     'name' => 'Sixt',
     'partner_code' => 'SX',
     'price' => '280.52',
     'tier' => '2',
  )),
  5 => 
  stdClass::__set_state(array(
     'name' => 'Alamo',
     'partner_code' => 'AL',
     'price' => '345.13',
     'tier' => '2',
  )),
  6 => 
  stdClass::__set_state(array(
     'name' => 'Advantage',
     'partner_code' => 'AD',
     'price' => '357.61',
     'tier' => '2',
  )),
  7 => 
  stdClass::__set_state(array(
     'name' => 'Enterprise',
     'partner_code' => 'ET',
     'price' => '364.46',
     'tier' => '2',
  )),
  8 => 
  stdClass::__set_state(array(
     'name' => 'Fox',
     'partner_code' => 'FX',
     'price' => '265.25',
     'tier' => '3',
  )),
  9 => 
  stdClass::__set_state(array(
     'name' => 'Payless',
     'partner_code' => 'ZA',
     'price' => '380.47',
     'tier' => '3',
  )),
  10 => 
  stdClass::__set_state(array(
     'name' => 'Dollar',
     'partner_code' => 'ZR',
     'price' => '385.99',
     'tier' => '3',
  )),
  11 => 
  stdClass::__set_state(array(
     'name' => 'Thrifty',
     'partner_code' => 'ZT',
     'price' => '385.99',
     'tier' => '3',
  )),
  12 => 
  stdClass::__set_state(array(
     'name' => 'Silvercar',
     'partner_code' => 'SC',
     'price' => '424.10',
     'tier' => '3',
  )),
  13 => 
  stdClass::__set_state(array(
     'name' => 'National',
     'partner_code' => 'NA',
     'price' => '448.82',
     'tier' => '3',
  )),
  14 => 
  stdClass::__set_state(array(
     'name' => 'Hertz',
     'partner_code' => 'HZ',
     'price' => '487.33',
     'tier' => '3',
  )),
)

I think this is a leaner method generating the same/desired result: (Demo)

$min=$results[0]->price;  // set initial/default min value
$index=0; // set initial/default index
foreach($results as $i=>$a){
    if($a->price<$min){  // if a lower price...
        $min=$a->price;  // store new $min
        $index=$i;  // stor new $index
    }
}
$results=array_merge($results,array_splice($results,$index,1));  // extract lowest and move to front of array
var_export($results);

1 Comment

@MichaelAlterio This is what you want, right? If not, you may need to overwrite my edit on your question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.