【问题标题】:Sorting in a php array在php数组中排序
【发布时间】:2009-07-21 16:05:49
【问题描述】:

我有这段代码可以打印出我的数据库中的列并为我添加一个“利润”列。 距离以复杂的方式计算,因此是在循环中完成的,而距离到“利润”的转换是在打印出来时完成的。

我想做的是按“利润”的降序打印出来。我相信(但不知道)最好的方法是将它们存储在一个数组中并“将它们排序”然后从那里打印出来。

如何确定将它们粘贴到数组的哪一行?
如何对数组进行排序?
如何循环遍历数组,以便无法将它们打印出来?

//display results
// now we retrieve the routes from the db
$query = "SELECT * FROM routes ORDER BY `id`;";

// run the query. if it fails, display error
$result = @mysql_query("$query") or die('<p class="error">There was an unexpected error grabbing routes from the database.</p>');

?>
<tr>
   <td style="background: url(http://www.teamdelta.byethost12.com/barbg.jpg) repeat-x top;">
      <center><b><font color="#F3EC84">»Matches«</font></b></center>
   </td>
</tr>

<tr>
<td style="background: #222222;">

</font>
<table border="0" width="100%"><tr>


<td width="10%"><b><center><b>Player</b></center></b></td>
<td width="10%"><center><b>Base</b></center></td>
<td width="10%"><b>Location</b></td>
<td width="5%"><b>Econ</b></td>
<td width="10%"><b>Distance</b></td>
<td width="10%"><center><b>Profit cred./h</b></center></td>
<td width="40%"><b>Comment</b></td>
<td width="5%"><align="right"><b>Delete</b></align></td>

</tr> 

<?

// while we still have rows from the db, display them
while ($row = mysql_fetch_array($result)) {

    $dname = stripslashes($row['name']);
    $dbase = stripslashes($row['base']);
    $dlocation = stripslashes($row['location']);
    $dx = stripslashes($row['x']);
    $dy = stripslashes($row['y']);
    $dgalaxy = stripslashes($row['galaxy']);
    $dplanet = stripslashes($row['planet']);
    $dcomment = stripslashes($row['comment']);
    $did = stripslashes($row['id']);
    $decon = stripslashes($row['econ']);

    $distance = -1 ;//default

    //distance calc
    if($dgalaxy == $galaxy)
    {//interstellar
       if(($dx == $x) && ($dy == $y))
       {//inter planitary
          if ((floor($planet/10)*10) == (floor($dplanet/10)*10))
          {// intra planitary loonar
             $distance = abs(fmod($planet,10)-fmod($planet,10))*0.1;  
          }
          else
          {// inter planitary
             $distance = abs((floor($planet/10)*10)-(floor($planet/10)*10))*0.2;  
          }
       }else
       {//interstllar
          $distance = round(Sqrt(pow(($dx-$x),2)+pow(($dy-$y),2)));//interstllar
       }
    }
    else
    {//intergalatic
       if ((floor($galaxy/10)*10) == (floor($dgalaxy/10)*10)) 
       {//intra galactic cluster
          $distance = abs(($galaxy-$dgalaxy))*200;
       }     
       else
       {//inter galactic cluster
          if ($galaxy < $dgalaxy)
          {//anti clockwise inter galactic cluster
             $distance = (((9-fmod($galaxy,10))*200)+2000+(fmod($dgalaxy,10)*200));
          }
          else
          {//clockwise inter galactic cluster
             $distance = (((fmod($galaxy,10))*200)+2000+(fmod(9-$dgalaxy,10)*200));
          }
       }
    }

    echo('<tr>
    <td width=\'20px\'><center>('.$dname.')</center></td>
    <td><center>'.$dbase.'</center></td>
    <td><a href="http://delta.astroempires.com/map.aspx?loc='.$dlocation.'">'.$dlocation.'</a></td>
    <td>'.$decon.'</td><td>'.$distance.' </td>
    <td>'.round(Sqrt(min($decon,$econ))*(1+Sqrt($distance)/75+Sqrt($players)/10)).'</td>
    <td>['.$dcomment.']</td>
    <td><a href=deleterouteconfirm.php?id='.$did.'>Delete</a></td>
    </tr>');
}
?></table><!--display results table-->

【问题讨论】:

    标签: php arrays sorting


    【解决方案1】:

    我认为最容易实施的解决方案是对您的数据库结果进行双重检查。

    第一遍将为每一行生成“距离”和“利润”值,并将这些行存储到我们将排序的数组中。

    第二遍将只是简单地循环遍历在第一遍中创建的数组并在正确排序和转义以输出后显示它们。

    <?php
    //display results
    // now we retrieve the routes from the db
    $query = "SELECT * FROM routes ORDER BY `id`;";
    
    // run the query. if it fails, display error
    $result = @mysql_query( "$query" ) or die( '<p class="error">There was an unexpected error grabbing routes from the database.</p>' );
    
    ?>
    <tr>
        <td
            style="background: url(http://www.teamdelta.byethost12.com/barbg.jpg) repeat-x top;">
        <center><b><font color="#F3EC84">»Matches«</font></b></center>
        </td>
    </tr>
    
    <tr>
        <td style="background: #222222;"></font>
        <table border="0" width="100%">
            <tr>
    
    
                <td width="10%"><b>
                <center><b>Player</b></center>
                </b></td>
                <td width="10%">
                <center><b>Base</b></center>
                </td>
                <td width="10%"><b>Location</b></td>
                <td width="5%"><b>Econ</b></td>
                <td width="10%"><b>Distance</b></td>
                <td width="10%">
                <center><b>Profit cred./h</b></center>
                </td>
                <td width="40%"><b>Comment</b></td>
                <td width="5%"><align="right"><b>Delete</b></align></td>
    
            </tr> 
    
    <?
    
    // while we still have rows from the db, display them
    $resultSet = array();
    while ( $row = mysql_fetch_array( $result ) )
    {
    
      $dname = stripslashes( $row['name'] );
      $dbase = stripslashes( $row['base'] );
      $dlocation = stripslashes( $row['location'] );
      $dx = stripslashes( $row['x'] );
      $dy = stripslashes( $row['y'] );
      $dgalaxy = stripslashes( $row['galaxy'] );
      $dplanet = stripslashes( $row['planet'] );
      $dcomment = stripslashes( $row['comment'] );
      $did = stripslashes( $row['id'] );
      $decon = stripslashes( $row['econ'] );
    
      $distance = -1; //default
    
    
      //distance calc
      if ( $dgalaxy == $galaxy )
      { //interstellar
        if ( ( $dx == $x ) && ( $dy == $y ) )
        { //inter planitary
          if ( ( floor( $planet / 10 ) * 10 ) == ( floor( $dplanet / 10 ) * 10 ) )
          { // intra planitary loonar
            $distance = abs( fmod( $planet, 10 ) - fmod( $planet, 10 ) ) * 0.1;
          } else
          { // inter planitary
            $distance = abs( ( floor( $planet / 10 ) * 10 ) - ( floor( $planet / 10 ) * 10 ) ) * 0.2;
          }
        } else
        { //interstllar
          $distance = round( Sqrt( pow( ( $dx - $x ), 2 ) + pow( ( $dy - $y ), 2 ) ) ); //interstllar
        }
      } else
      { //intergalatic
        if ( ( floor( $galaxy / 10 ) * 10 ) == ( floor( $dgalaxy / 10 ) * 10 ) )
        { //intra galactic cluster
          $distance = abs( ( $galaxy - $dgalaxy ) ) * 200;
        } else
        { //inter galactic cluster
          if ( $galaxy < $dgalaxy )
          { //anti clockwise inter galactic cluster
            $distance = ( ( ( 9 - fmod( $galaxy, 10 ) ) * 200 ) + 2000 + ( fmod( $dgalaxy, 10 ) * 200 ) );
          } else
          { //clockwise inter galactic cluster
            $distance = ( ( ( fmod( $galaxy, 10 ) ) * 200 ) + 2000 + ( fmod( 9 - $dgalaxy, 10 ) * 200 ) );
          }
        }
      }
      $row['distance'] = $distance;
      $row['profit'] = round( Sqrt( min( $decon, $econ ) ) * ( 1 + Sqrt( $distance ) / 75 + Sqrt( $players ) / 10 ) );
      $resultSet[] = $row;
    }
    
    //  Perform custom sort
    usort( $resultSet, 'sorter' );
    function sorter( $a, $b )
    {
      if ( $a['profit'] == $b['profit'] ) return 0;
      return ( $a['profit'] < $b['profit'] ) ? -1 : 1;
    }
    
    //  Switch to "descending"
    array_reverse( $resultSet );
    
    //  Output escape the values
    $safeForHtml = array_map( 'htmlspecialchars', $resultSet );
    
    foreach( $safeForHtml as $row )
    {
      echo ( '<tr>
                    <td width=\'20px\'><center>(' . $row['name'] . ')</center></td>
                    <td><center>' . $row['base'] . '</center></td>
                    <td><a href="http://delta.astroempires.com/map.aspx?loc=' . $row['location'] . '">' . $row['location'] . '</a></td>
                    <td>' . $row['econ'] . '</td>
                    <td>' . $row['distance'] . ' </td>
                    <td>' . $row['profit'] . '</td>
                    <td>[' . $row['comment'] . ']</td>
                    <td><a href=deleterouteconfirm.php?id=' . $row['id'] . '>Delete</a></td>
                    </tr>' );
    }
    ?>
    </table>
        <!--display results table-->
    

    【讨论】:

    • 感谢您全部输入,但它似乎不起作用,它会在适当的时间内循环通过最终输出,但会打印空白.. 在这里运行teamdelta.byethost12.com/postroute.php put D03:53:32:21 作为 location 和 econ 作为数字,其他可以只是随机字符串评论,玩家是可选的。
    • 我发现了这个问题。我砍掉了“$safeForHtml = array_map('htmlspecialchars', $resultSet);”并从 $resultSet 打印并打印...但没有按顺序...
    • 好的,更改排序器并删除数组反转及其工作 :) 谢谢
    【解决方案2】:

    您正在从 MySQL 获取数据。为什么不直接从查询中对结果进行排序?

    $query = "SELECT * FROM routes ORDER BY `profit` DESC, `id`;";
    

    编辑:重新阅读您的问题,利润不是一个字段,但您可能希望用您的利润值填充表格,而不是每次都重新计算。

    编辑 2: 或者,保护您的输出,计算您的利润,将所有内容放入一个数组中,然后使用以下内容:

    $resultArray; //Your array with all your rows plus a profit key-value pair.
    
    $sortedArray = array_msort($resultArray, array('profit'=>SORT_DESC));
    
    // array_msort by cagret at gmail dot com
    function array_msort($array, $cols)
    {
        $colarr = array();
        foreach ($cols as $col => $order) {
            $colarr[$col] = array();
            foreach ($array as $k => $row) { $colarr[$col]['_'.$k] = strtolower($row[$col]); }
        }
        $params = array();
        foreach ($cols as $col => $order) {
            $params[] =& $colarr[$col];
            $params = array_merge($params, (array)$order);
        }
        call_user_func_array('array_multisort', $params);
        $ret = array();
        $keys = array();
        $first = true;
        foreach ($colarr as $col => $arr) {
            foreach ($arr as $k => $v) {
                if ($first) { $keys[$k] = substr($k,1); }
                $k = $keys[$k];
                if (!isset($ret[$k])) $ret[$k] = $array[$k];
                $ret[$k][$col] = $array[$k][$col];
            }
            $first = false;
        }
        return $ret;
    
    }
    

    【讨论】:

    • 我不认为他知道利润,直到它在代码中计算出来:round(Sqrt(min($decon,$econ))*(1+Sqrt($distance)/75+Sqrt($players)/10)
    【解决方案3】:
    猜你喜欢
    • 2010-10-04
    • 1970-01-01
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    • 2013-01-03
    • 1970-01-01
    相关资源
    最近更新 更多