0

I have this kind of array

ID - CLASS - PRICE - NAME
1 - 1 - 400 - Product 1
2 - 3 - 120 - Product 2
3 - 1 - 350 - Product 3
4 - 2 - 600 - Product 4
5 - 2 - 320 - Product 5

I need to sort items in array by CLASS, but only when CLASS is equal "1", these items sort by PRICE, ASC and then sort the rest of array items only by PRICE (I don't care CLASS in this case anymore).

The result of sorting should be:
ID
3 (has CLASS == 1 and lower price then 1)
1 (has CLASS == 1 and higher price then 3)
2 (has CLASS != 1 (so rest of items sort only by price), lowest price)
5 (has CLASS != 1, middle price)
4 (has CLASS != 1, higher price)

I found and edit this function, which works fine with multiarrays and multi-sorting, but I can not figure out how to sort only part of array by CLASS I wrote above.

function sortMultiArray() {
      $args = func_get_args();
      $data = array_shift($args);
      foreach($args as $n => $field) {
        if (is_string($field)) {
          $tmp = array();
          foreach($data as $key => $row) {
            $tmp[$key] = str_replace("-1", "999999999", $row[$field]);
          }
          $args[$n] = $tmp;
        }
      }

      $args[] = &$data;
      call_user_func_array('array_multisort', $args);
      return array_pop($args);
}

// usage - sorting by price DESC, name ASC
$sortedArray = sortMultiArray($array, "price", SORT_DESC, 'name', SORT_ASC);
sylar32
  • 197
  • 3
  • 16
  • 2
    You don’t want to sort “part of an array”, that makes little sense. And using array_multisort does not make much sense here either. What you want to do, is simply use usort, and in your own little callback function that compares two items, you want to apply multiple criteria to figure out which one is to be considered “greater” then the other. – CBroe Jan 31 '18 at 15:08
  • A `usort` callback would roughly do: if one of the items has class 1 and the other doesn't, the class 1 item is higher. Otherwise, compare the items by price. (I don't know if that encapsulates your entire logic, it's a bit opaque.) – deceze Jan 31 '18 at 15:12
  • But I need to compare by price even items with CLASS == 1, but only to each other with CLASS == 1. And then compare items with other CLASS by price also. Can I do it only with usort? The array I need to sort i much complicated, multidimensional, but I simplified it for better understanding. – sylar32 Jan 31 '18 at 16:03
  • Again, the logic is: *is one item class 1 and the other isn't? Then the class 1 item is higher, end the comparison. Otherwise (either both items are class 1 or both items are not class 1), compare the price.* That's it. That causes class 1 items to go first and be sorted by price and the rest to be sorted by price after class 1 items. In SQL terms: `ORDER BY IF(class = 1, 0, 1), price`. – deceze Jan 31 '18 at 16:59
  • Thx, If someone would need, this works function sort123($a, $b) { if($a['class'] == 1 && $b['class'] == 1) { return ($a['price'] > $b['price'] ? 1 : -1); } else if ($a['class'] == 1) { return -1; } else if ($b['class'] == 1) { return 1; } else { return ($a['price'] > $b['price'] ? 1 : -1); } } – sylar32 Jan 31 '18 at 22:46
  • I'd have opted for a less redundant `if ($a['class'] == 1 xor $b['class'] == 1) ... else return $a['price'] - $b['price'];`… – deceze Feb 01 '18 at 14:36

0 Answers0