0

I am trying to calculate percentiles for users in a database. In order to do this I have a $data array that I need to sort.

I have a query object that contains User_ID, Total_User_Orders, and Total_Orders. Here's how the code looks so far:

// Loop through the users
foreach($query->result() as $row)
{
    (string)$user_id = (string)$row->user_id;

    $data[$user_id] = number_format((($row->total_user_orders/$row->total_orders)*100), 5);
}

// Sort the $data array
array_multisort($data);

print_r($data);

What (I believe) that should do is typecast $row->user_id (an int) as a string. Then, the $data[$user_id] index should be set as a string - right...?

When I sort the array using array_multisort it sorts it as though the index was an Integer, rather than a String. This means it loses the index.

The PHP manual for array_multisort() states, "Associative (string) keys will be maintained, but numeric keys will be re-indexed.". I have also tried using array_multisort($data, SORT_STRING), but the same output occurs. However - it does work when I do $data['#'.$user_id], but this doesn't quite feel like the right solution to me!

Can anyone help? Thanks in advance!

4
  • 1
    Assuming you are trying to sort by User ID, $data doesn't look multi-dimensional here, why can't you use asort()? php.net/manual/en/function.asort.php
    – Greg K
    Commented Feb 23, 2012 at 12:41
  • No, I'm trying to sort by the value (number_format([...]) etc). But I want to retain the user ID as a key so that I can link up the User ID with their Percentile value later on.
    – Jack
    Commented Feb 23, 2012 at 12:55
  • Having just said that... asort() seems to have done the trick just fine!
    – Jack
    Commented Feb 23, 2012 at 12:56
  • Apologies, I didn't mean sort by user ID, that's the key, asort() will sort by the value of the array and maintain the association.
    – Greg K
    Commented Feb 23, 2012 at 14:49

2 Answers 2

2

I think you're overcomplicating things. With no testing, I'd think indexing the $data-array like this would work:

$data[(string)$row->user_id] = ...

or

$data[''.$user_id] = ...

EDIT:
Otherwise you could build your array multi-dimensional and sort by one of the indices, like this:

foreach($query->result() as $row) {
  $data[] = array(
    'user_id' => $row->user_id,
    'percent' => number_format((($row->total_user_orders/$row->total_orders)*100), 5);
  );
}

Or you could index by the percentage and sort by the keys (using ksort()):

foreach($query->result() as $row) {
  $data[number_format((($row->total_user_orders/$row->total_orders)*100), 5)] = $row->user_id];
}

The last solution could be dangerous if several users have the same percentage.

Personally I would probably go with the asort() solution mentioned above.

3
  • I've just tried both suggestions and I still get exactly the same output. I will edit my question to clarify what print_r() is outputting.
    – Jack
    Commented Feb 23, 2012 at 12:54
  • I don't think it'll work because I remember having this problem already, and when the key is a number PHP will re-index the table, even if you explicitly cast it as a string (but it's been a while and I didn't retest since).
    – rlanvin
    Commented Feb 23, 2012 at 12:57
  • I've updated my answer to give more ideas for solving this (and similar) problem. Depends on the specific needs which is best.
    – Flygenring
    Commented Feb 23, 2012 at 13:25
1

As described in my comment, array_multisort() is not what you are after here. You don't have multiple arrays or a multi-dimensional array.

To maintain the key => value association in the array and sort the contents use asort().

foreach ($query->result() as $row) {
    $percent = ($row->total_user_orders / $row->total_orders) * 100;
    $data[$row->user_id] = number_format($percent, 5);
}
asort($data);

If you want descending percentages reverse the array after it's been sorted.

$data = array_reverse($data, true);

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.