简体   繁体   English

uasort()吗? -从银行帐户分类帖子

[英]uasort() ? - sorting posts from a bank account

How can I sort an array with some posts from a bank account? 如何使用银行帐户中的某些帖子对数组进行排序?

I need to sort by three fields: date, amount, accumulated amount 我需要按三个字段排序:日期,金额,累计金额

ie. 即。

date | amount | accum_amount
01-01-11 500 500 ('amount' + previous 'accum_amount' = 'accum_amount' => 500 + 0 = 500)
01-01-11 100 600 ('amount' + previous 'accum_amount' = 'accum_amount' => 100 + 500 = 600)
01-02-11 -25 575 ('amount' + previous 'accum_amount' = 'accum_amount' => -25 + 600 = 575)
01-02-11 150 725 ('amount' + previous 'accum_amount' = 'accum_amount' => 150 + 575 = 725)
01-03-11 200 925 ('amount' + previous 'accum_amount' = 'accum_amount' => 200 + 725 = 925)
01-04-11 -25 900 ('amount' + previous 'accum_amount' = 'accum_amount' => -25 + 925 = 900)

btw. 顺便说一句 the date field is an UNIX timestamp 日期字段是UNIX时间戳

array(
    array(
        'time' => 1200000000,
        'amount' => 500,
        'accum_amount' => 500
        ),
    array(
        'time' => 1200000000,
        'amount' => 150,
        'accum_amount' => 725
        ),
    array(
        'time' => 1200000000,
        'amount' => 100,
        'accum_amount' => 600
        ),
    array(
        'time' => 1300000000,
        'amount' => 200,
        'accum_amount' => 925
        ),
    array(
        'time' => 1300000000,
        'amount' => -25,
        'accum_amount' => 900
        ),
    array(
        'time' => 1200000000,
        'amount' => -25,
        'accum_amount' => 575
        )
    )

Change your array structure to something like: 将您的数组结构更改为:

$tmp = array(
   time => array(1200000000, 1200000000, 1200000000, ...),
   amount => array(500, 150, 100, ...),
   accum_amount => array(500, 725, 600, ...),
)

and then use array_multisort for sorting (http://php.net/manual/en/function.array-multisort.php) like: 然后使用array_multisort进行排序(http://php.net/manual/en/function.array-multisort.php),例如:

array_multisort($tmp['time'], SORT_ASC, $tmp['amount'], SORT_DESC, $tmp['accum_amount'], SORT_ASC);

It's not very intuitive, but it should work. 它不是很直观,但是应该可以。

Of course you can write a helper function to map the new sorting order on other array structure. 当然,您可以编写一个辅助函数以将新的排序顺序映射到其他数组结构上。

Example: 例:

function mySort($array, $sort) {
    $tmp = array();
    foreach ($array as $row) {
        foreach ($row as $field => $value) {
            if (!isset($tmp[$field])) {
                $tmp[$field] = array();
            }

            $tmp[$field][] = $value;
        }
    }

    $params = array();
    foreach ($sort as $field => $direction) {
        $params[] = $tmp[$field];
        $params[] = $direction;
    }

    $keys = array_keys($array);
    $params[] =& $keys;

    call_user_func_array('array_multisort', $params);

    $result = array();
    foreach ($keys as $key) {
        $result[$key] = $array[$key];
    }

    return $result;
}

Call: 呼叫:

$data = mySort($data, array(
    'time' => SORT_ASC,
    'amount' => SORT_ASC,
    'accum_amount' => SORT_ASC
));

function usort() is made for this purpose: 函数usort()用于此目的:

usort($data, "my_sort");

function my_sort($row1, $row2) {
  if ($row1['time']<$row2['time']) return -1;
  if ($row1['time']>$row2['time']) return 1;
  if ($row1['amount']<$row2['amount']) return -1;
  if ($row1['amount']>$row2['amount']) return 1;
  if ($row1['accum_amount']<$row2['accum_amount']) return -1;
  if ($row1['accum_amount']>$row2['accum_amount']) return 1;
  return 0;
}

Your example isnt really clear what you want. 您的示例并不清楚您想要什么。 You don't describe it this way, but from example it appears you want to sort by date increasing, then accum_amount increasing, then amount (increasing?) 您没有用这种方式描述它,但是从示例看来,您想按日期升序排序,然后按accum_amount升序,然后按金额(升序?)

You just have to write a comparison function and pass it to uasort along with your array 您只需要编写一个比较函数并将其与数组一起传递给uasort

 $comp = function($a,$b) 
         {
            if ($a['date'] != $b['date'])
                 return $a['date'] - $b['date'];
            else if ($a['accum_amount'] != $b['accum_amount']) 
                 return $a['accum_amount'] - $b['accum_amount'];
            return $a['amount'] - $b['amount'];
         }

 uasort($arr, $comp);

You might find a function like this helpful. 您可能会发现这样的功能很有帮助。 It will create the comparison function when given an array, in order of importance, of the keys to compare by. 当给定一个按重要性排列的键数组时,它将创建比较函数。 (All ascending, support for descending would necessarily complicate it a good deal) (所有升序,对降序的支持一定会使它复杂化很多)

$compMakerAsc = function($l)
                {
                  return function($a, $b) use ($l)
                  {
                    foreach($l as $k)
                    {
                        if ($a[$k] != $b[$k])
                           return $a[$k] - $b[$k]; 
                           //OR return ($a[$k] > $b[$k]) ? 1 : -1; 
                    }
                    return 0;
                 }

$myComp = $compMakerAsc('date', 'accum_amount', 'amount');
$uasort($arr, $myComp);
$key = 'accum_amount';

function sortme($a, $b)
{
    global $key;
    if ($a[$key] == $b[$key]) {
        return 0;
    }
    return ($a[$key] < $b[$key]) ? -1 : 1;
}

usort($array, "sortme");

perhaps this should help. 也许这应该有所帮助。 Bad thing, have to define global variable. 不好的事情,必须定义全局变量。 Complete code!!! 完整的代码!!!

$array = array(
    array(
        'time' => 1200000000,
        'amount' => 500,
        'accum_amount' => 500
        ),
    array(
        'time' => 1200000000,
        'amount' => 150,
        'accum_amount' => 725
        ),
    array(
        'time' => 1200000000,
        'amount' => 100,
        'accum_amount' => 600
        ),
    array(
        'time' => 1300000000,
        'amount' => 200,
        'accum_amount' => 925
        ),
    array(
        'time' => 1300000000,
        'amount' => -25,
        'accum_amount' => 900
        ),
    array(
        'time' => 1200000000,
        'amount' => -25,
        'accum_amount' => 575
        )
    );

$key = 'accum_amount';

function sortme($a, $b)
{
    global $key;
    if ($a[$key] == $b[$key]) {
        return 0;
    }
    return ($a[$key] < $b[$key]) ? -1 : 1;
}

usort($array, "sortme");

echo "<pre>";
print_r($array);
echo "</pre>";

Let's combine this from the comments 让我们结合评论

the query is just as simple as SELECT time, amount, accum_amount FROM table 查询就像SELECT time, amount, accum_amount FROM table一样简单

with this requirement from the original question: 原始问题有以下要求:

I need to sort by three fields: date, amount, accumulated amount 我需要按三个字段排序:日期,金额,累计金额

Now, there were no requirements stated as to whether the sort is ascending or not. 现在,没有关于分类是否递增的要求。 Let's assume ascending. 让我们假设升序。

SELECT time, amount, accum_amount 
  FROM table
 ORDER BY time ASC, amount ASC, accum_amount ASC

This will give us all of the data first sorted by time. 这将为我们提供所有首先按时间排序的数据。 When the time is identical, it will sort second by amount, lowest first and highest last. 当时间相同时,它将按数量排在第二位 ,从最低到最高,最后到高。 When the time and amount are identical, it will sort third by the accumulated amount, again sorted lowest first, highest last. 当时间数量相同时,它将按累计数量排序第三 ,再次按照最低,最高,最后的顺序排序。

Changing the order of operations with the sort is as simple as swapping around the list in the ORDER BY clause. 通过排序更改操作顺序就像在ORDER BY子句中的列表周围交换一样简单。 Going from largest to smallest is as easy as switching from ASC to DESC . 从最大到最小就像从ASC切换到DESC一样容易。

Note how relatively easy this method is in comparison to sorting in PHP. 请注意,与PHP中的排序相比,此方法相对容易。 Whenever you can, let your database give you pre-sorted results. 只要有可能,就让数据库为您提供预排序的结果。


Because I need to leave the site for a few hours, I'm just going to type this up real quick. 因为我需要离开网站几个小时,所以我只想快速输入一下。 I'm operating right now under the assumption that you want to recalculate the accumulated value . 我现在正在假设您要重新计算累计值

Our query is now: 现在,我们的查询是:

SELECT time, amount
  FROM table
 ORDER BY time ASC, amount DESC

We'll be a friendly bank and perform all deposits (increases in amount) first, then all debits (decreases in amount) last, processing the largest debits later than the smaller debits. 我们将成为一家友好的银行,首先执行所有存款(金额增加),然后执行所有借方(金额减少),然后处理较大的借项,然后处理较小的借项。

Given $data is our array: 给定$data是我们的数组:

$running_total = 0;
foreach($data as $index => $row) {
    $data[$index]['accum_amount'] = $running_total + $row['amount'];
    $running_total = $data[$index]['accum_amount'];
}

This should successfully rebuild the accum_amount list, given the business rules I have outlined above. 鉴于我上面概述的业务规则,这应该可以成功地重建accum_amount列表。

我发现在将数据放入数据库之前的另一种方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM