7

I have the following array:

$arr = [
    [
        'user_id' => 1,
        'product_id' => 1
    ],
    [
        'user_id' => 1,
        'product_id' => 2
    ],
    [
        'user_id' => 1,
        'product_id' => 3
    ],
    [
        'user_id' => 2,
        'product_id' => 1
    ],
    [
        'user_id' => 2,
        'product_id' => 2
    ],
    [
        'user_id' => 3,
        'product_id' => 1
    ]
];

And I want to sort it so it looks like this:

$arr = [
    [
        'user_id' => 1,
        'product_id' => 1
    ],
    [
        'user_id' => 2,
        'product_id' => 1
    ],
    [
        'user_id' => 3,
        'product_id' => 1
    ],
    [
        'user_id' => 1,
        'product_id' => 2
    ],
    [
        'user_id' => 2,
        'product_id' => 2
    ],
    [
        'user_id' => 1,
        'product_id' => 3
    ]
];

So basically I need to order by product_id and user_id in such a way that it selects the lower number product_id from each user before proceeding to the next.

I tried to use usort but I couldn't get it to work.

usort($campaigns, function($a, $b){
    if($a['product_id'] == $b['product_id']){
        return 0;
    }

    if($a['product_id'] < $b['product_id']){

        if($a['user_id'] == $b['user_id']){
            return 1;
        }

        if($a['user_id'] < $a['user_id']){
            return 0;
        }

        return -1;
    }else{

        if($a['user_id'] == $a['user_id']){
            return -1;
        }

        if($a['user_id'] < $a['user_id']){
            return 0;
        }

        return 1;
    }
});

I also tried array_multisort but all I could get it to do is to order using the same order that I already retrieve from the database.

2
  • your code with usort is incorrect; you should compare to </> by first field, and only if first fields are equals compare by second. Commented Apr 12, 2016 at 6:07
  • 2
    You are saying you are retrieving from database, any reason why you are not sorting directly on the query? Commented Apr 12, 2016 at 6:09

3 Answers 3

3

Assumption is your values is integers:

usort($campaigns, function($a, $b){
    if($a['product_id'] == $b['product_id']){
        return $a['user_id'] - $b['user_id'];
    } else {
        return $a['product_id'] - $b['product_id'];
    }
});

Also you can use database ordering with ORDER BY product_id, user_id clause.

Sign up to request clarification or add additional context in comments.

Comments

2

Solution using array_multisort function with "array of columns"(few sorting dimensions):

$userIds = $productIds = [];
foreach ($arr as $k => $v) {
    $userIds[$k] = $v['user_id'];
    $productIds[$k] = $v['product_id'];
}

array_multisort($productIds, SORT_ASC, $userIds, SORT_ASC, $arr);

print_r($arr);

The output:

Array
(
    [0] => Array
        (
            [user_id] => 1
            [product_id] => 1
        )

    [1] => Array
        (
            [user_id] => 2
            [product_id] => 1
        )

    [2] => Array
        (
            [user_id] => 3
            [product_id] => 1
        )

    [3] => Array
        (
            [user_id] => 1
            [product_id] => 2
        )

    [4] => Array
        (
            [user_id] => 2
            [product_id] => 2
        )

    [5] => Array
        (
            [user_id] => 1
            [product_id] => 3
        )

)

Comments

1
$arrTags = [
    [
        'user_id' => 1,
        'product_id' => 1
    ],
    [
        'user_id' => 1,
        'product_id' => 2
    ],
    [
        'user_id' => 1,
        'product_id' => 3
    ],
    [
        'user_id' => 2,
        'product_id' => 1
    ],
    [
        'user_id' => 2,
        'product_id' => 2
    ],
    [
        'user_id' => 3,
        'product_id' => 1
    ]
];

foreach($arrTags as $key => $row){ 
$userArray[$key]  = $row['user_id'];
$productArray[$key] = $row['product_id'];
}

array_multisort($productArray, SORT_ASC, $userArray, SORT_ASC, $arrTags);
print_r($arrTags);

Output

 Array
(
    [0] => Array
        (
            [user_id] => 1
            [product_id] => 1
        )

    [1] => Array
        (
            [user_id] => 2
            [product_id] => 1
        )

    [2] => Array
        (
            [user_id] => 3
            [product_id] => 1
        )

    [3] => Array
        (
            [user_id] => 1
            [product_id] => 2
        )

    [4] => Array
        (
            [user_id] => 2
            [product_id] => 2
        )

    [5] => Array
        (
            [user_id] => 1
            [product_id] => 3
        )

)

You can also check in online editor. Click Here

4 Comments

Your output is not the same as OP's expected one. Also your comment about checking your answer is complete noise and useless.
While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Please also try not to crowd your code with explanatory comments, this reduces the readability of both the code and the explanations!
Please check my edited code. I just forgot to chage $userArray and $productArray in multisort. I have edited code and output also checked in below linked editor. I am not brilliant and expert like you but I am trying my best to give useful answer to user. @Rizier123
Sorry for inconvenience for this answer as I have attached output without checking its my fault. Mistake was interchanged of array in array_multisort($productArray, SORT_ASC, $userArray, SORT_ASC, $arrTags); @Rizier123

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.