8

我有一个数组,其中包含有关许多航班的信息。我只想要五个最低的价格。

首先,我创建一个循环按价格对数组进行排序。

其次我打印前五个数组

但这需要更多时间..我怎样才能减少这个时间?

foreach ($flights_result->json_data['response']['itineraries'] as $key => $value)
{
    $mid[$key] = $value['price']['totalAmount'];
}

//Sort the data with mid descending
//Add $data as the last parameter, to sort by the common key
array_multisort($mid, SORT_ASC, $flights_result->json_data['response']['itineraries']);

// print 5 arrays
foreach ($flights_result->json_data['response']['itineraries'] as  $value)
{
    echo 'departureTime:' . $value['inboundInfo']['departureTime'] . '</br>';
    echo 'layoverInMin:' . $value['inboundInfo']['layoverInMin'] . '</br>';
    //      // loop echo 

    foreach ($value['inboundInfo']['flightNumbers'] as $flightNumbers)
    {
        echo 'flightNumbers  :' . $flightNumbers . '</br>';
    }

    echo 'durationInMin:' . $value['inboundInfo']['durationInMin'] . '</br>';
    echo 'localDepartureTimeStr:' . $value['inboundInfo']['localDepartureTimeStr'] . '</br>';
    echo ' arrivalTime:' . $value['inboundInfo']['arrivalTime'] . '</br>';
    echo ' numStops:' . $value['inboundInfo']['numStops'] . '</br>';

    ////     loop 
    foreach ($value[' inboundInfo']['flightClasses'] as $flightClasses)
    {
        echo 'flightClasses name :' . $flightClasses['name'] . '</br>';
        echo 'flightClasses fareClass :' . $flightClasses['fareClass'] . '</br>';
    }

    echo 'localArrivalTimeStr:' . $value['inboundInfo']['localArrivalTimeStr'] . '</br>';
    //      loop  echo

    foreach ($value[' carrier'] as $carrier)
    {
        echo 'carrier name :' . $carrier['name'] . '</br>';
        echo 'carrier code :' . $carrier['code'] . '</br>';
    }

    echo 'amount:' . $value['price']['amount'] . '</br>';
    echo ' totalAmount :' . $value['price']['totalAmount'] . '</br>';
    echo 'pricePerPassenger:' . $value['price']['pricePerPassenger'] . '</br>';
    echo 'currencyCode: ' . $value['price']['currencyCode'] . '</br>';
    echo 'totalPricePerPassenger: ' . $value['price']['totalPricePerPassenger'] . '</br>';
    echo 'includesTax: ' . $value['price ']['includesTax'] . '</br>';
    echo 'destinationCountryCode:' . $value[' destinationCountryCode'] . ' </br> -------- </br>';

    $count++;
    if ($count > 2)
    {
        break;
    }
}

数组示例

Array
(
    [0] => Array
        (
            [ecpcRank] => 0
            [inboundInfo] => Array
                (
                    [aircraftTypes] => Array
                        (
                        )

                    [departureTime] => 1381448400000
                    [layoverInMin] => 1359
                    [flightNumbers] => Array
                        (
                            [0] => DL3672
                            [1] => EK204
                            [2] => EK923
                        )

                    [durationInMin] => 2360
                    [airportsExpanded] => Array
                        (
                            [0] => PHL
                            [1] => JFK
                            [2] => JFK
                            [3] => DXB
                            [4] => DXB
                            [5] => CAI
                        )

                    [localDepartureTimeStr] => 2013/10/10 18:40 -0500
                    [airports] => Array
                        (
                            [0] => PHL
                            [1] => JFK
                            [2] => DXB
                            [3] => CAI
                        )

                    [arrivalTime] => 1381590000000
                    [numStops] => 2
                    [flightClasses] => Array
                        (
                            [0] => Array
                                (
                                    [name] => Economy
                                    [fareClass] => 1
                                )

                            [1] => Array
                                (
                                    [name] => Economy
                                    [fareClass] => 1
                                )

                            [2] => Array
                                (
                                    [name] => Economy
                                    [fareClass] => 1
                                )

                        )

                    [localArrivalTimeStr] => 2013/10/12 17:00 +0200
                )

            [location] => Array
                (
                    [0] => Array
                        (
                            [code] => CAI
                            [name] => Cairo
                        )

                    [1] => Array
                        (
                            [code] => DXB
                            [name] => Dubai
                        )

                    [2] => Array
                        (
                            [code] => PHL
                            [name] => Philadelphia
                        )

                    [3] => Array
                        (
                            [code] => JFK
                            [name] => New York J F Kennedy
                        )

                    [4] => Array
                        (
                            [code] => MXP
                            [name] => Milan Malpensa
                        )

                )

            [carrier] => Array
                (
                    [0] => Array
                        (
                            [name] => Delta Air Lines
                            [code] => DL
                        )

                    [1] => Array
                        (
                            [name] => US Airways
                            [code] => US
                        )

                    [2] => Array
                        (
                            [name] => Emirates
                            [code] => EK
                        )

                    [3] => Array
                        (
                            [name] => Egyptair
                            [code] => MS
                        )

                )

            [bookingType] => WEBSITE
            [price] => Array
                (
                    [name] => 
                    [nameOTA] => 
                    [description] => 
                    [amount] => 26280
                    [totalAmount] => 26280
                    [pricePerPassenger] => 26280
                    [currencyCode] => EGP
                    [totalPricePerPassenger] => 26280
                    [includesTax] => 1
                )

            [generatedDate] => 1380212804686
            [providerId] => emirates.com
            [id] => MS703[CAI-MXP],EK205[MXP-JFK],US3407[JFK-PHL]|DL3672[PHL-JFK],EK204[JFK-DXB],EK923[DXB-CAI]
            [originCountryCode] => EG
            [bookingCode] => 13600077136293253
            [destinationCountryCode] => US
            [outboundInfo] => Array
                (
                    [aircraftTypes] => Array
                        (
                        )

                    [departureTime] => 1380958800000
                    [layoverInMin] => 1050
                    [flightNumbers] => Array
                        (
                            [0] => MS703
                            [1] => EK205
                            [2] => US3407
                        )

                    [durationInMin] => 1940
                    [airportsExpanded] => Array
                        (
                            [0] => CAI
                            [1] => MXP
                            [2] => MXP
                            [3] => JFK
                            [4] => JFK
                            [5] => PHL
                        )

                    [localDepartureTimeStr] => 2013/10/05 09:40 +0200
                    [airports] => Array
                        (
                            [0] => CAI
                            [1] => MXP
                            [2] => JFK
                            [3] => PHL
                        )

                    [arrivalTime] => 1381075200000
                    [numStops] => 2
                    [flightClasses] => Array
                        (
                            [0] => Array
                                (
                                    [name] => Economy
                                    [fareClass] => 1
                                )

                            [1] => Array
                                (
                                    [name] => Economy
                                    [fareClass] => 1
                                )

                            [2] => Array
                                (
                                    [name] => Economy
                                    [fareClass] => 1
                                )

                        )

                    [localArrivalTimeStr] => 2013/10/06 11:00 -0500
                )

        )

    [1] => Array
        (
            [ecpcRank] => 0
            [inboundInfo] => Array
                (
                    [aircraftTypes] => Array
                        (
                        )

                    [departureTime] => 1381448400000
                    [layoverInMin] => 1359
                    [flightNumbers] => Array
                        (
                            [0] => DL3672
                            [1] => EK204
                            [2] => EK923
                        )

                    [durationInMin] => 2360
                    [airportsExpanded] => Array
                        (
                            [0] => PHL
                            [1] => JFK
                            [2] => JFK
                            [3] => DXB
                            [4] => DXB
                            [5] => CAI
                        )

                    [localDepartureTimeStr] => 2013/10/10 18:40 -0500
                    [airports] => Array
                        (
                            [0] => PHL
                            [1] => JFK
                            [2] => DXB
                            [3] => CAI
                        )

                    [arrivalTime] => 1381590000000
                    [numStops] => 2
                    [flightClasses] => Array
                        (
                            [0] => Array
                                (
                                    [name] => Economy
                                    [fareClass] => 1
                                )

                            [1] => Array
                                (
                                    [name] => Economy
                                    [fareClass] => 1
                                )

                            [2] => Array
                                (
                                    [name] => Economy
                                    [fareClass] => 1
                                )

                        )

                    [localArrivalTimeStr] => 2013/10/12 17:00 +0200
                )

            [location] => Array
                (
                    [0] => Array
                        (
                            [code] => CAI
                            [name] => Cairo
                        )

                    [1] => Array
                        (
                            [code] => PHL
                            [name] => Philadelphia
                        )

                    [2] => Array
                        (
                            [code] => DXB
                            [name] => Dubai
                        )

                    [3] => Array
                        (
                            [code] => JFK
                            [name] => New York J F Kennedy
                        )

                )

            [carrier] => Array
                (
                    [0] => Array
                        (
                            [name] => Delta Air Lines
                            [code] => DL
                        )

                    [1] => Array
                        (
                            [name] => Emirates
                            [code] => EK
                        )

                )

            [bookingType] => WEBSITE
            [price] => Array
                (
                    [name] => 
                    [nameOTA] => 
                    [description] => 
                    [amount] => 28183
                    [totalAmount] => 28183
                    [pricePerPassenger] => 28183
                    [currencyCode] => EGP
                    [totalPricePerPassenger] => 28183
                    [includesTax] => 1
                )

            [generatedDate] => 1380212804689
            [providerId] => emirates.com
            [id] => EK928[CAI-DXB],EK203[DXB-JFK],DL6122[JFK-PHL]|DL3672[PHL-JFK],EK204[JFK-DXB],EK923[DXB-CAI]
            [originCountryCode] => EG
            [bookingCode] => 13600077139546083
            [destinationCountryCode] => US
            [outboundInfo] => Array
                (
                    [aircraftTypes] => Array
                        (
                        )

                    [departureTime] => 1380966900000
                    [layoverInMin] => 947
                    [flightNumbers] => Array
                        (
                            [0] => EK928
                            [1] => EK203
                            [2] => DL6122
                        )

                    [durationInMin] => 2118
                    [airportsExpanded] => Array
                        (
                            [0] => CAI
                            [1] => DXB
                            [2] => DXB
                            [3] => JFK
                            [4] => JFK
                            [5] => PHL
                        )

                    [localDepartureTimeStr] => 2013/10/05 11:55 +0200
                    [airports] => Array
                        (
                            [0] => CAI
                            [1] => DXB
                            [2] => JFK
                            [3] => PHL
                        )

                    [arrivalTime] => 1381093980000
                    [numStops] => 2
                    [flightClasses] => Array
                        (
                            [0] => Array
                                (
                                    [name] => Economy
                                    [fareClass] => 1
                                )

                            [1] => Array
                                (
                                    [name] => Economy
                                    [fareClass] => 1
                                )

                            [2] => Array
                                (
                                    [name] => Economy
                                    [fareClass] => 1
                                )

                        )

                    [localArrivalTimeStr] => 2013/10/06 16:13 -0500
                )

        )

)

4

8 回答 8

4

要回答您的问题:

但它需要更多时间..如何减少这个大时间?

在你可以减少之前,你需要找出更多的确切来源。正如您在评论中所写,您正在使用远程请求来获取数据。

对您提供的数据进行数组排序非常快,因此我假设您不需要优化数组排序,只需优化从远程获取数据的时间和方式即可。这样做的一种方法是缓存它或预取它或进行并行处理。但是到目前为止的细节根本不重要,除非你已经发现更多的来自哪里,以便清楚什么是造成大时间的原因,然后可以考虑减少它。

希望到目前为止这对您有所帮助,并随时将缺失的信息添加到您的问题中。

你可以在这里看到仅数组的代码,它真的很快:

您可以在输出下方找到执行统计信息,示例如下:

好的(0.008 秒真实,0.006 秒墙,14 MB,99 系统调用)

于 2013-10-01T12:14:13.327 回答
2

你真的应该安装一个分析器(XHProf)并检查究竟是什么花费了这么多时间。

我认为这是排序,因为foreach通过 5 个元素的最终数组应该很快。那你为什么要排序呢?如果排序的唯一目的是找到 5 个“最低”项目,那么最快的方法就是只找到 5 个最低项目:

$min5 = array();
foreach ($flights_result->json_data['response']['itineraries'] as $key => $value)
{
    $amount = $value['price']['totalAmount'];

    // Just put first 5 elements in our result array
    if(count($min5) < 5) {
        $min5[$key] = $amount;
        continue;
    }
    // Find largest element of those 5 we check
    $maxMinK = null;
    foreach($min5 as $minK=>$minV) {
        if($maxMinK === null) {
            $maxMinK = $minK;
            continue;
        }
        if($minV > $min5[$maxMinK])
        {
            $maxMinK = $minK;
        }
    }
    // If our current amount is less than largest one found so far,
    // we should remove the largest one and store the current amount instead
    if($amount < $min5[$maxMinK])
    {
        unset($min5[$maxMinK]);
        $min5[$key] = $amount;
    }
}
asort($min5); // now we can happily sort just those 5 lowest elements

它将找到 5 个项目O(6n),在您的情况下,这些项目应该比O(n²)排序的潜力更好;然后你可以像这样使用它:

foreach($min5 as $key=>$minValue)
{
    $intinerary = $flights_result->json_data['response']['itineraries'][$key]
    ...
}

如果是排序的话,这应该会快很多!所以得到那个XHprof并检查:)

于 2013-09-29T08:58:40.163 回答
1

这是我会做的:

<?php

    // Initialize html Array
    $html = array();

    // Iterate Over Values, Using Key as Label.
    foreach( $value['inboundInfo'] as $inboundLabel => &$inboundValue )
    {
        // Check for Special Cases While Adding to html Array
        if( $inboundLabel == 'flightNumbers' )
        {
            $html[] = $inboundLabel . ': ' . implode( ', ', $inboundValue );
        }
        elseif( $inboundLabel == 'flightClasses' )
        {
            foreach( $inboundValue as $fcName => &$fcValue )
            {
                $html[] = 'flightClasses ' . $fcName . ': ' . $fcValue;
            }
        }
        else
        {
            $html[] = $inboundLabel . ': ' . $inboundValue;
        }
    }

    // Don't Need Foreach to Complicate Things Here
    $html[] = 'carrier name: ' . $value[' carrier']['name'];
    $html[] = 'carrier code: ' . $value[' carrier']['code'];

    // Add Price Info to Array
    foreach( $value['price'] as $priceLabel => &$price )
    {
        $html[] = $priceLabel . ': ' . $price;
    }
    $html[] = ' -------- </br>';

    // And Finally:
    echo implode( "<br/>\r\n", $html );

要么就是这样,要么编写一个递归函数来遍历所有数据。另请注意,这仅在您的数据符合您想要的顺序时才有效。

于 2013-09-26T17:04:03.703 回答
0

我会做以下事情:

// This is optional, it just makes the example more readable (IMO)
$itineraries = $flights_result->json_data['response']['itineraries'];

// Then this should sort in the smallest way possible
foreach ($flights_result->json_data['response']['itineraries'] as $key => $value) {
     $mid[$key] = $value['price']['totalAmount'];
}

// Sort only one array keeping the key relationships.
asort($mid);

// Using the keys in mid, since they are the same as the keys in the itineraries
// we can get directly to the data we need.
foreach($mid AS $key => $value) {
     $value = $itineraries[$key];

     // Then continue as above, I think your performance issue is the sort
     ...
}
于 2013-09-26T16:47:39.533 回答
0

缓冲区回显/打印(即,不要从内部循环回显/打印):

$buffer = "";

for ($i = 0; $i < 1000; $i++) {
    $buffer .= "hello world\n";
}

print($buffer);

在您的情况下,这可能可以忽略不计,但值得为更大的迭代次数做。

如果您只对 5 个最低价格感兴趣,则无需对整个数组进行排序。

循环遍历数组,同时维护具有 5 个最低价格的键列表。

我对 PHP 太生疏了,无法有效地提供示例。

于 2013-09-26T16:50:06.527 回答
0

我看到两个潜在的领域会减慢代码的速度:

  • 对数组进行排序
  • Echoing + string 连接所有这些字符串

我会首先找出导致滞后的区域。如果分析很困难,您可以在代码中插入调试打印语句,每个语句都打印当前时间。这会给你一个粗略的想法,即哪个代码区域占用了大部分时间。就像是:

echo "Time at this point is " . date();

一旦我们得到这些结果,我们就可以进一步优化。

于 2013-09-30T17:51:56.563 回答
0

试试这个...

$arr_fli = array(0 => array('f_name'=> 'Flight1', 'price' => 2000),
                 1 => array('f_name'=> 'Flight1', 'price' => 5000),
                 3 => array('f_name'=> 'Flight1', 'price' => 7000),
                 4 => array('f_name'=> 'Flight1', 'price' => 4000),
                 5 => array('f_name'=> 'Flight1', 'price' => 6000),
                 6 => array('f_name'=> 'Flight1', 'price' => 800),
                 7 => array('f_name'=> 'Flight1', 'price' => 1000),
                 8 => array('f_name'=> 'Flight1', 'price' => 500)
            );
foreach($arr_fli as $key=>$flights) {
    $fl_price[$flights['price']] = $flights;
}
sort($fl_price);
$i = 0;
foreach($fl_price as $final) {
    $i++;
    print_r($final);
    echo '<br />';
    if($i==5) {
        break;
    }
}
于 2013-10-01T11:22:25.810 回答
0

首先要了解的是代码的哪一部分需要很长时间才能执行。一种快速而肮脏但简单的方法是使用您的记录器。我假设您已经在使用它来记录您在代码运行时想要保留的所有其他信息,例如内存使用量、磁盘使用量、用户请求、购买等。

你的记录器可以是一个高度复杂的工具(只是谷歌的“登录框架”或类似的工具),或者像你的文件的消息写入器一样简单。为了快速开始,您可以使用类似的东西:

class Logger {
  private $_fileName;
  private $_lastTime;

  public function __construct ($fileName) {
    $this->_fileName = $fileName;
    $this->_lastTime = microtime(true);
  }

  public function logToFile ($message) {
    // open file for writing by appending your message to the end of the file
    $file = fopen($this->_fileName, 'a');
    fwrite($file, $message . "\n");
    fclose($file);
  }

  // optional for testing - see your logs quickly without bothering with files
  public function logToConsole($message) {
    echo $message;
  }

  // optional $message to add, e.g. about what happened in your code
  public function logTimePassed ($message = '') {
    $timePassed = microtime(true) - $this->_lastTime;
    //$this->logToConsole("Milliseconds Passed since last log: " . $timePassed . ", " . $message . "\n");
    $this->logToFile("Milliseconds Passed since last log: " . $timePassed . ", " . $message . "\n");
    // reset time
    $this->_lastTime = microtime(true);
  }
}

// before your code starts
$myLogFileName = 'my-logs'; // or whatever the name of the file to write in
$myLogger = new Logger($myLogFileName);

// ... your code goes ...

// after something interesting
$myLogger->logTimePassed(); // log time since last logging

// ... your code continues ...

// after something else, adding a message for your record
$myLogger->logTimePassed("after sorting my flight array"); 

现在,您可以检查您的代码并将您的记录器放置在所有可能需要很长时间的任何关键点之后。添加您的消息以了解发生了什么。延迟的地方可能有很多。通常在内存中完成的数组操作非常快。但更耗时的操作需要更多注意,例如:

  • 文件读/写,目录访问
  • 数据库访问
  • HTTP 请求

例如,http 请求 - 您echo的 s 是否通过网络立即发送到浏览器?它们是否每次都在循环中发送?如果是,您可能想避免它。如其他答案所示,将它们保存到数组中,或使用Output Buffering

为了进一步减少对服务器的 http 请求,您可以尝试在客户端放置更多功能并使用 ajax 仅从服务器检索真正需要的内容。

也不要忘记隐藏的东西。例如,我看到对象属性访问:

$flights_result->json_data

这个对象是如何实现的?它只在内存中吗?它是否调用外部服务?如果是,那可能是你的罪魁祸首。然后你必须努力优化它。通过缓存它们来减少查询的数量,优化您的数据以便您只需要查询更改等。所有这些都取决于您的应用程序的结构,并且可能与您的其余代码无关。如果您需要任何帮助,您显然需要将此信息放入您的问题中。

基本上任何没有完全在内存中完成的事情都会导致延迟。至于内存中的操作,除非你的数据很大或者你的操作很密集,否则它们的影响可能可以忽略不计。尽管如此,如果您有任何疑问,只需将您的记录器放在所有“可疑”的地方。


现在对于您的特定代码,它混合了各种东西,例如外部对象访问、数组值访问、数组排序、回显输出,也许还有其他隐藏的东西。这使得甚至很难知道将时间记录器放在哪里。

更容易的是使用面向对象的方法并遵循分离关注点的原则(google on that)。这样你的对象和它们的方法将有单一的职责,你会很容易地看到谁在做什么以及在哪里放置你的记录器。

我不能高度推荐“鲍勃叔叔”的传奇书来了解更多关于它的信息。我认为您的代码来自函数内部。根据鲍勃叔叔的说法:

函数的第一条规则是它们应该很小。第二条规则是它们应该比那个小。

函数应该做一件事。他们应该做得很好。他们应该只这样做。

将代码拆分为更多函数时,您必须为这些函数赋予有意义的名称,从而大大提高代码的可读性。不用说,所有不打算在类外使用的函数都应该是私有的,因此您可以通过继承轻松地重用您的类。


有很多事情可以做,但为了让您入门,这里有一些想法:

  • 将您的数据数组封装到一个对象中,其中只使用您需要的方法。像这样的东西:

    class Itineraries {
      private $_itineraryArray;
    
      public function __construct(array $itineraryArray) {
        $this->_itineraryArray = $itineraryArray;
      }
    
      public function getNCheapest ($number) {
        $this->_sortByPrice();
        $result = array();
        for ($i=0; $i< $number; $i++) {
          $result[] = $this->_itineraryArray[$i];
        }
        return $result;
      }
    
      private function _sortByPrice() {
        $prices = $this->_getPriceArray();
        array_multisort($prices, SORT_ASC, $this->_itineraryArray);
      }
    
      private function _getPriceArray () {
        foreach ($this->_itineraryArray as $entry) {
          $this->_getPrice($entry);  
        }
      }
    
      private function _getPrice($entry) {
        return $entry['price']['totalAmount']; // or whatever it is
      }
    }
    
    //Then you instantiate your object:
    $myItineraries = new Itineraries($flights_result->json_data['response']['itineraries']); // or whatever
    

请注意,如果您的数组结构完全改变,您只需要调整方法_getPrice 和单行来实例化您的对象!您的其余代码将保持不变!

这是模型-视图-控制器范式中模型层的一部分。你可以用谷歌搜索找到很多信息。该模型知道如何处理其数据,但对它们的来源一无所知,没有浏览器输出,没有 http 请求等。

  • 然后负责生成用户输出的所有内容都进入您的视图层或所谓的演示层,在那里您有其他对象处理它。你所有的“回声”都会放在这里。像这样的东西:

    class Presenter {
      public function outputNCheapest ($myItineraries, $number) {
        $outputData = $myItineraries->getNCheapest ($number);
        echo $this->generateOutput($outputData);
      }
    
      private function _generateOutput($outputData) {
        $html = '';
        // your html string is generated
        return $html;
      }
    }
    

但是,我个人反对在服务器上生成 HTML。这只是浪费带宽和用户等待响应的时间。每次我等待浏览器重新加载整个页面时,我都希望开发人员阅读此内容。您可以输出 JSON 而不是 HTML,并在客户端使用 ajax 或其他方式请求它。

此外,您用户的浏览器可以缓存一些数据而不是再次请求它们,并决定请求什么。这将进一步减少您的用户的延迟,而这正是您所关心的。

于 2013-10-03T18:15:46.973 回答