2

I need help to sort array by couple of logics

[
  {
    "id": 1,
    "status": "pending",
    "date": "2019-08-01"
  },
  {
    "id": 2,
    "status": "delivered",
    "date": "2019-08-01"
  },
  {
    "id": 3,
    "status": "pending",
    "date": "2019-08-03"
  },
  {
    "id": 4,
    "status": "delivered",
    "date": "2019-08-03"
  },
  {
    "id": 5,
    "status": "delivered",
    "date": "2019-08-02"
  }
]

what I want to do is to sort the array to status pending show first, and then sort it by the date descending

I already test to using sortByDesc from laravel collection but the array looks like sorted it by just 1 function

$collection = $collection->sortByDesc('date')->sortByDesc(function ($row, $key) {
      if($row['status'] == 'pending'){
         return 1;
      }else{
         return 0;
      }
});

My expected final result look like this :

[
  {
    "id": 3,
    "status": "pending",
    "date": "2019-08-03"
  },
  {
    "id": 1,
    "status": "pending",
    "date": "2019-08-01"
  },
  {
    "id": 4,
    "status": "delivered",
    "date": "2019-08-03"
  },
  {
    "id": 5,
    "status": "delivered",
    "date": "2019-08-02"
  },
  {
    "id": 2,
    "status": "delivered",
    "date": "2019-08-01"
  }
]
2
  • What is the unexpected behaviour of your tested method result? Commented Aug 30, 2019 at 4:49
  • @TharakaDilshan its sorted by status only not the date Commented Aug 30, 2019 at 4:59

3 Answers 3

1

Few solutions:

  1. Use a custom callback and return an array source
$products->sortBy(function($product) {
            return [$product->param1, $product->param2];
 });

This will sort a collection by param2 first, and then by param1

  1. Use a custom callback and return a composite property to sort on source
$posts = $posts->sortBy(function($post) {
    return sprintf('%-12s%s', $post->column1, $post->column2);
});
  1. Sort your array by column 1, then split it up by column 2 and then merge it again (untested).
$collection->sortByDesc('date');
$collection->groupBy('status');
$collection->keyBy('status');

EDIT: Also I'm not sure if sortByDesc('date') works with date strings.

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

1 Comment

thanks solution number 1 works, I barely know sortby can return array value
0

Your expected result can be achieved like this.

$sorted = $collection
              ->sortByDesc('date')
              ->sortBy(function ($item) {
                  return 'pending' == $item['status'] ? 0 : 1;
              })
              ->values();

2 Comments

I tried your method, but the result is only sorted by status, field date return unsorted like before..
I tested this one and I got your expected result.
0

To be more precise:

      $collection= $collection->sort(
        function ($a, $b) {
            if(($a->status== $b->status) &&($a->status== 'pending')){
                return ($a->date >= $b->date) ? -1 : 1;
            }elseif($a->status== 'pending' && ($a->status!= $b->status)){
                return 1;
            }else{
                return ($a->date <= $b->date) ? 1 : -1;
            }
        }
    );
    $collection= $collection->sortByDesc('status');

Comments

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.