RK Ahir
RK Ahir

Reputation: 105

Sort multilevel array on sub key value in PHP

I want to sort below multilevel array on ascending order of price value.

{
    "pData": [
    {
        "name": "Walmart",
        "address": "Full Address for Walmart",
        "pricing": [{
            "id": "Samsung Galaxy 21M",
            "price": 157.0,
        }],
    },
    {
        "name": "Stop & Shop",
        "address": "Full Address for Stop & Shop",
        "pricing": [{
            "id": "Samsung Galaxy 21M",
            "price": 142.0,
        }],
    },
    {
        "name": "Safeway",
        "address": "Full Address for Safeway",
        "pricing": [{
            "id": "Samsung Galaxy 21M",
            "price": 148.0,
        }],
    }
    ],
    "status ":" ok "
}

I tried below code but giving same result without sorting array on value of price key. I even tried many similar codes from different answers on this site but none of working. So please advise what is wrong with my code or suggest completely different code.

function cmp($a, $b)
{
    //if ($a["price"] == $b["price"]) // Try #1
    if($a["pData"]["pricing"]["price"] == $b["pData"]["pricing"]["price"]) // Try #2
    {
        return 0;
    }
    return ($a["price"] < $b["price"]) ? -1 : 1; // Try #1
    return ($a["pData"]["pricing"]["price"] < $b["pData"]["pricing"]["price"]) ? -1 : 1;
}

usort($result,"cmp");
print_r($result);

Upvotes: 1

Views: 43

Answers (2)

JSowa
JSowa

Reputation: 10612

You can use spaceship operator <=> also known as three-way comparison operator.

usort($result["pData"], function ($a, $b) {
    return $a["pricing"][0]["price"] <=> $b["pricing"][0]["price"];});

For PHP 7.4 with arrow function.

usort($result["pData"], fn($a, $b) => $a["pricing"][0]["price"] <=> $b["pricing"][0]["price"]);

Upvotes: 1

Alex Barker
Alex Barker

Reputation: 4400

You should be pretty close with what you have. You don't need the pData index in your callback, instead pass $result['pData'] to usort.

function cmp($a, $b)
{
    if ($a["pricing"][0]["price"] == $b["pricing"][0]["price"])
    {
        return 0;
    }

    return ($a["pricing"][0]["price"] < $b["pricing"][0]["price"]) ? -1 : 1;
}

usort($result["pData"],"cmp");
print_r($result);

I just noticed that you have an array of objects at the pricing element, so sorting the pData element in its current form will be problematic. You may want to pull all of the pricing elements out into a seperate data structure first and then sort that new structure. Something like this may help you get to a better working solution:

$tmp = array();
foreach ($result["pData"] as $pData) {
    foreach ($pData["pricing"] as $pricing) {
        $tmp[] = array(
            "name" => $pData["name"],
            "address" => $pData["address"],
            "id" => $pricing["id"],
            "price" => $pricing["price"]
        );
    }
}

function cmp($a, $b)
{
    if ($a["price"] == $b["price"])
    {
        return 0;
    }

    return ($a["price"] < $b["price"]) ? -1 : 1;
}

usort($tmp,"cmp");
print_r($tmp);

Upvotes: 1

Related Questions