Jump to content

Help sorting an array by two arguments


charlysole

Recommended Posts

Hi everyone

This is quite difficult to explain....

i have the following code:
     // Calculate total ordinal ranking.
      uasort($totals, "sort_totals");
      $ordinal = 0;
      $last_ordinal = 0;
      $high_score = 0;
      $last_score = 100000;
      foreach ($totals as $uid => $u_object) {
        $ordinal++;
        if ($u_object['total'] < $last_score) {
          $last_ordinal = $ordinal;
          $last_score = $u_object['total'];
          if ( $ordinal == 1 ) {
            $high_score = $last_score;
          }
        }
        $totals[$uid]['ranking'] = $last_ordinal;
        $totals[$uid]['pts_back'] = $high_score - $last_score;
      }
      cache_set($cache_key, $totals);
    }
    $cache_totals[$cache_key] = $totals;
  }


  return $cache_totals[$cache_key];
}
function sort_totals($a, $b) {
  if ($a['total'] > $b['total']) {
    return -1;
  }
  elseif ($a['total'] < $b['total']) {
      return 1;
  }
  else {
    if ($a['name'] < $b['name']) {
      return -1;
    }
    elseif ($a['name'] > $b['name']) {
        return 1;
    }
    else {
      return 0;
    }
  }
}

This code sorts the totals arranging them major to minor. And thats ok... it works.

 

Now I also have another parameter called "exact" here: .... $u_object['exact'] 

Who contains an integer showing the number of times a user has matched the exact result.

 

What i want to do is use
$u_object['exact'] 

as a second arrangement parameter number...

 

Example

For the following stored data:

User 1:  100 points, and 4 matches.

User 2:  90  points, and 2 matches.

User 4: 100 points and 7 matches.

 

The result should be:

User 4: 100 points and 7 matches.

User 1:  100 points, and 4 matches.

User 2:  90  points, and 2 matches.

 

As you can see 2 the first sort is by total, and the second by matches

 

How can i do this?

 

Thanks in advice.

And sorry for my poor english!

 

 

Link to comment
Share on other sites

$u_object is the same array as $a and $b in the comparison function (sort_totals). You have some branching logic in there to handle [total] and [name] so all you have to do is extend it with another comparison using [exact] in between.

 

function sort_totals($a, $b) {
  if ($a['total'] > $b['total']) {
    return -1;
  }
  elseif ($a['total'] < $b['total']) {
      return 1;
  }
  else {
    if ($a['exact'] > $b['exact']) {
      return -1;
    }
    elseif ($a['exact'] < $b['exact']) {
      return 1;
    }
    else {
      if ($a['name'] < $b['name']) {
        return -1;
      }
      elseif ($a['name'] > $b['name']) {
          return 1;
      }
      else {
        return 0;
      }
    }
  }
}
Getting rather long, though, isn't it? The good news is that there's a much better way of doing all those comparisons, and it's possible because the return value from the function merely has to be negative, zero, or positive - not strictly -1, 0, or 1.

 

For the numbers, you can replace "if $x strcmp. However both of those will immediately return 0 if the two values are the same, when you need it to do the next comparison instead. You can use the ternary operator ?: for this, using the first value if it is truthy (non-zero) and the second value if it is false-y (zero).

 

If that made even a little bit of sense, great. Here's the code:

function sort_totals($a, $b) {
  return ($b['total'] - $a['total']) // higher total first
      ?: ($b['exact'] - $a['exact']) // or else higher exact first
      ?: strcmp($a['name'], $b['name']) // or else name in alphabetical order
  ;
}
If you understand the deal with using subtraction/strcmp() then it's easier to add more conditions in here too - though you're probably not likely to need to do that.
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.