-1

I am stuck on a PHP concept that seems simple to me at first :

I have this array :

$test = array(
    array(
        'quantity' => 0,
        'nbr_sales' => 10
    ),
    array(
        'quantity' => 10,
        'nbr_sales' => 100
    ),
    array(
        'quantity' => 10,
        'nbr_sales' => 1250
    ),
    array(
        'quantity' => 20,
        'nbr_sales' => 5000
    ),
    array(
        'quantity' => -1,
        'nbr_sales' => 990
    ),
    array(
        'quantity' => 0,
        'nbr_sales' => 1000
    )
);

I want to sort this multidimensional array by checking if quantity is positive or negative, then by nbr_sales (DESC), so a result like this :

$result = array(
    array(
        'quantity' => 20,
        'nbr_sales' => 5000
    ),
    array(
        'quantity' => 10,
        'nbr_sales' => 1250
    ),
    array(
        'quantity' => 10,
        'nbr_sales' => 100
    ),
    array(
        'quantity' => 0,
        'nbr_sales' => 1000
    ),
    array(
        'quantity' => 0,
        'nbr_sales' => 10
    ),
    array(
        'quantity' => -1,
        'nbr_sales' => 990
    )
);

I tried several approaches but nothing really conclusive :

$result = array();
$positives = array(); $negatives = array();
foreach($test as $t) {
    $t['quantity'] > 0 ? array_push($positives, $t) : array_push($negatives, $t);
}
usort($positives, function($a, $b){
    return $a['nbr_sales'] == $b['nbr_sales'] ? 0 : ($a['nbr_sales'] < $b['nbr_sales'] ? 1 : -1);
});
usort($negatives, function($a, $b){
    return $a['nbr_sales'] == $b['nbr_sales'] ? 0 : ($a['nbr_sales'] < $b['nbr_sales'] ? 1 : -1);
});
array_push($result, $positives);
array_push($result, $negatives);

var_dump($result)

array(2) {
  [0] => array(3) {
    [0] => array(2) {
      ["quantity"] => int(20)
      ["nbr_sales"]=> int(5000)
    }
    [1]=> array(2) {
      ["quantity"] => int(10)
      ["nbr_sales"]=> int(1250)
    }
    [2] => array(2) {
      ["quantity"] => int(10)
      ["nbr_sales"]=> int(100)
    }
  }
  [1]=> array(3) {
    [0] => array(2) {
      ["quantity"] => int(0)
      ["nbr_sales"]=> int(1000)
    }
    [1]=> array(2) {
      ["quantity"]=> int(-1)
      ["nbr_sales"] => int(990)
    }
    /* should be above */
    [2]=> array(2) {
      ["quantity"] => int(0)
      ["nbr_sales"] => int(10)
    }
  }
}

Thanks for your help :)

aurepito
  • 101
  • 11
  • Please share your effort and explain where and how exactly it failed to do what you need. Posting a question without showing what you tried is an express lane to get your question closed with a canonical target such as [this one](https://stackoverflow.com/questions/17364127/how-can-i-sort-arrays-and-data-in-php). – El_Vanja May 11 '21 at 13:10

2 Answers2

0

You want to sort in two steps. So use a callback to do exactly that:

<?php
$data = [
  [
    'quantity' => 0,
    'nbr_sales' => 10
  ], [
    'quantity' => 10,
    'nbr_sales' => 100
  ], [
    'quantity' => 10,
    'nbr_sales' => 1250
  ], [
    'quantity' => 20,
    'nbr_sales' => 5000
  ], [
    'quantity' => -1,
    'nbr_sales' => 990
  ], [
    'quantity' => 0,
    'nbr_sales' => 1000
  ]
];

usort($data, function($a, $b) {
  $q = $b['quantity'] <=> $a['quantity'];
  if ($q != 0) return $q;
  return $b['nbr_sales'] <=> $a['nbr_sales'];
});

print_r($data);

If you prefer a trinary notation that would be the equivalent:

usort($data, function($a, $b) {
  return 
    0 == $b['quantity'] - $a['quantity']
      ? $b['nbr_sales'] <=> $a['nbr_sales'] 
      : $b['quantity'] <=> $a['quantity'];
});

The output obviously is:

Array
(
    [0] => Array
        (
            [quantity] => 20
            [nbr_sales] => 5000
        )
    [1] => Array
        (
            [quantity] => 10
            [nbr_sales] => 1250
        )
    [2] => Array
        (
            [quantity] => 10
            [nbr_sales] => 100
        )
    [3] => Array
        (
            [quantity] => 0
            [nbr_sales] => 1000
        )
    [4] => Array
        (
            [quantity] => 0
            [nbr_sales] => 10
        )
    [5] => Array
        (
            [quantity] => -1
            [nbr_sales] => 990
        )
)
arkascha
  • 41,620
  • 7
  • 58
  • 90
0

Visually, it's not the result I'm searching for. For example if I change

$data = [
    [
        'quantity' => 0,
        'nbr_sales' => 10
    ], [
        'quantity' => 10000, // change here
        'nbr_sales' => 100
    ], [
        'quantity' => 10,
        'nbr_sales' => 1250
    ], [
        'quantity' => 20,
        'nbr_sales' => 5000
    ], [
        'quantity' => -1,
        'nbr_sales' => 990
    ], [
        'quantity' => 0,
        'nbr_sales' => 1000
    ]
];

usort($data, function($a, $b) {
    $q = $b['quantity'] - $a['quantity'];
    if ($q != 0) return $q;
    return $b['nbr_sales'] - $a['nbr_sales'];
});

I get this :

array(6) {
  [0]=> array(2) {
    ["quantity"]=> int(10000)
    ["nbr_sales"]=> int(100)
  }
  [1]=> array(2) {
    ["quantity"]=> int(20)
    ["nbr_sales"]=> int(5000)
  }
  [2]=> array(2) {
    ["quantity"]=> int(10)
    ["nbr_sales"]=> int(1250)
  }
  [3]=> array(2) {
    ["quantity"]=> int(0)
    ["nbr_sales"]=> int(1000)
  }
  [4]=> array(2) {
    ["quantity"]=> int(0)
    ["nbr_sales"]=> int(10)
  }
  [5]=> array(2) {
    ["quantity"]=> int(-1)
    ["nbr_sales"]=> int(990)
  }
}

But I'm looking for this :

array(6) {
  [0]=> array(2) {
    ["quantity"]=> int(20)
    ["nbr_sales"]=> int(5000)
  }
  [1]=> array(2) {
    ["quantity"]=> int(10)
    ["nbr_sales"]=> int(1250)
  }
  [2]=> array(2) {
    ["quantity"]=> int(10000)
    ["nbr_sales"]=> int(100)
  }
  [3]=> array(2) {
    ["quantity"]=> int(0)
    ["nbr_sales"]=> int(1000)
  }
  [4]=> array(2) {
    ["quantity"]=> int(0)
    ["nbr_sales"]=> int(10)
  }
  [5]=> array(2) {
    ["quantity"]=> int(-1)
    ["nbr_sales"]=> int(990)
  }
}
aurepito
  • 101
  • 11
  • Is this "answer" meant as a comment to my answer here? If so you will need to explain further. What you now write contradicts what you wrote in the question. You will need to explain the logic of sorting. Why should 10000 be considered _smaller_ then 10? – arkascha May 11 '21 at 14:01
  • (I'll delete this answer :-) ) As I said I want to check if quantity if positive or negative : If positive, I want to sort first by nbr_result DESC then by qty ASC Then if negative, I want to sort first by qty ASC then by nbr_result DESC – aurepito May 11 '21 at 14:11
  • Sorting by that column _does_ tell positive and negative apart. You will have to explain further... Because if by that you mean that apart from the sign of the column "quantity" only the order of the column "nbr_sales" should count, then again your proposed result does not make any sense: 1000 is not smaller than 100. So you need to explain further... – arkascha May 11 '21 at 14:14