代码之家  ›  专栏  ›  技术社区  ›  Alex Rashkov

重构JavaScript和PHP代码[工作面试]

  •  2
  • Alex Rashkov  · 技术社区  · 14 年前

    最近我有一个工作面试。我有两个任务:

    // The library 'jsUtil' has a public function that compares 2 arrays, returning true if
    // they're the same. Refactor it so it's more robust, performs better and is easier to maintain.
    /**
      @name jsUtil.arraysSame
      @description Compares 2 arrays, returns true if both are comprised of the same items, in the same order
      @param {Object[]} a Array to compare with
      @param {Object[]} b Array to compare to
      @returns {boolean} true if both contain the same items, otherwise false
      @example
      if ( jsUtil.arraysSame( [1, 2, 3], [1, 2, 3] ) ) {
        alert('Arrays are the same!');
      }
    */
    // assume jsUtil is an object
    
    jsUtil.arraysSame = function(a, b) {
      var r = 1;
      for (i in a) if ( a[i] != b[i] ) r = 0;
        else continue;
        return r;
    }
    

    2) 重构检查闰年的PHP函数

    <?php
    /*
      The class 'DateUtil' defines a method that takes a date in the format DD/MM/YYYY, extracts the year
      and works out if it is a leap year. The code is poorly written. Refactor it so that it is more robust
      and easier to maintain in the future.
    
      Hint: a year is a leap year if it is evenly divisible by 4, unless it is also evenly
      divisible by 100 and not by 400.
    */
    
    class DateUtil {
        function notLeapYear ($var) {
            $var = substr($var, 6, 4);
            if (! ($var % 100) && $var % 400) {
                return 1;
            }
            return $var % 4;
        }
    }
    
    
    $testDates = array('03/12/2000', '01/04/2001', '28/01/2004', '29/11/2200');
    
    /* the expected result is
    * 03/12/2000 falls in a leap year
    * 01/04/2001 does not fall in a leap year
    * 28/01/2004 falls in a leap year
    * 29/11/2200 does not fall in a leap year
    */
    ?>
    
    <? $dateUtil = new DateUtil(); ?>
    <ul>
      <? foreach ($testDates as $date) { ?>
        <li><?= $date ?> <?= ($dateUtil->notLeapYear($date) ? 'does not fall' : 'falls') ?> in a leap year</li>
      <? } ?>
    </ul>
    

    我想我能应付这项任务,但我不太确定,我仍然没有得到他们的答复,而且已经一个星期了。你能举一个例子说明你处理这些任务的方法吗?我真的很感激。稍后我可以发布我的解决方案/代码。

    好的,这是我对问题的回答。

    <?php // Always use full/long openning tags not 
    
    $start = microtime(true);
    
    class DateUtil {
    
        /**
         * The date could be used in other 
         * class methods in the future.
         * Use just internally.
         **/
        var $_date; 
    
        /**
         * The constructor of the class takes
         * 1 argument, date, as a string and sets
         * the object parameter _date to be used
         * internally. This is compatable only in PHP5
         * for PHP4 should be replaced with function DateUtil(...)
         */
        public function __construct( $date = '' ) {
            $this->_date = $date;
        }
    
        /**
         * Setter for the date. Currently not used.
         * Also we could use _set magical function.
         * for PHP5.
        **/
        public function setDate( $date = '' ) {
            $this->_date = $date;
        }
    
        /**
         * Gettre of the date. Currently not used.
         * Also we could use _get magical function.
         * for PHP5.
        **/
        public function getDate() {
            return $this->_date;
        }
    
        public function isLeapYear( $year = '' ) {
            // all leap years can be divided through 4
            if (($year % 4) != 0) {
                return false;
            }
    
            // all leap years can be divided through 400
            if ($year % 400 == 0) {
                return true;
            } else if ($year % 100 == 0) {
                return false;
            }
    
            return true;
        }
    }
    
    $dates = array('03/12/2000', '01/04/2001', '30/01/2004', '29/11/2200');
    $dateUtil = new DateUtil();
    
    foreach($dates as $date) {
        /** 
         * This processing is not done in the class
         * because the date format could be different in 
         * other cases so we cannot assume this will allways 
         * be the format of the date
         * 
         * The php function strtotime() was not used due to 
         * a bug called 2K38, more specifically dates after and 2038
         * are not parsed correctly due to the format of the UNIX 
         * timestamp which is 32bit integer.
         * If the years we use are higher than 1970 and lower
         * than 2038 we can use date('L', strtotime($date));
        **/
        $year = explode('/', $date);
        $year = $year[2];
        $isLeap = $dateUtil->isLeapYear($year);
    
        echo '<pre>' . $date . ' - ';
        echo ($isLeap)? 'Is leap year': 'Is not leap year';
        echo '</pre>';
    }
    
    echo 'The execution took: ' . (microtime(true) - $start) . ' sec';
    ?>
    

    JavaScript

    /***************************************************/
    
    jsUtil = new Object();
    
    jsUtil.arraysSame = function(a, b) {
    
    
        if( typeof(a) != 'object') {
            // Check if tepes of 'a' is object
            return false;
        } else if(typeof(a) != typeof(b)) {
            // Check if tepes of 'a' and 'b' are same
            return false;
        } else if(a.length != b.length) {
            // Check if arrays have different length if yes return false
            return false;
        }
    
        for(var i in a) {
            // We compare each element not only by value
            // but also by type so 3 != '3'
            if(a[i] !== b[i]) {
                return false;
            }
        }
    
        return true;
    }
    
    // It will work with associative arrays too
    var a = {a:1, b:2, c:3};
    var b = {a:1, b:2, c:3};    // true
    var c = {a:1, b:2, g:3};    // false
    var d = {a:1, b:2, c:'3'};  // false
    
    var output = '';
    
    output += 'Arrays a==b is: ' + jsUtil.arraysSame( a, b );
    output += '\n';
    output += 'Arrays a==c is: ' + jsUtil.arraysSame( a, c );
    output += '\n';
    output += 'Arrays a==d is: ' + jsUtil.arraysSame( a, d );
    
    alert(output);
    
    5 回复  |  直到 14 年前
        1
  •  3
  •   Marc B    14 年前

    对于PHP版本:

    class DateUtil {
        function LeapYear ($var) {
            $date = DateTime::CreateFromFormat($var, 'd/m/Y');
            return($date->format('L')); // returns 1 for leapyear, 0 otherwise
        }
        function notLeapYear($var) {
            return(!$this->LeapYear($var)) {
        }
    }
    
        2
  •  5
  •   Tim Down    14 年前

    使用 for for...in . 如果数组不同,则希望尽快返回,因此从长度比较开始,遇到两个数组之间不同的元素时立即返回。用严格不等式算子比较 !== . 在数组中向后迭代以获得速度,并通过指定 a i 再利用 作为迭代变量。

    此代码假定 b Array 物体。这个问题似乎暗示了这一点。

    var jsUtil = jsUtil || {};
    
    jsUtil.arraysSame = function(a, b) {
        var i = a.length;
        if (i != b.length) return false;
        while (i--) {
            if (a[i] !== b[i]) return false;
        }
        return true;
    };
    
        3
  •  1
  •   szanata    14 年前

    第一个问题也许我可以帮你:

    var jsUtil = jsUtil || {};
    
    jsUtil.arraysSame = function(a, b){
        //both must be arrays
        if (!a instanceof Array || !b instanceof Array) {
            return false;
        }
        //both must have the same size
        if (a.length !== b.length) {
            return false;
        }
    
        var isEquals = true;
        for (var i = 0, j = a.length; i < j; i++) {
            if (a[i] !== b[i]) {
    
                isEquals = false;
                i = j; //don't use break
            }
        }
        return isEquals;
    }
    

    我包括打字检查,让事情更清楚。

        4
  •  0
  •   Jon Snyder    14 年前

    1) 使用将数组转换为字符串的函数。有许多可用的库,根据您已经使用的库,您可能需要使用不同的库。你可以在 Json.org

    jsUtil.arraysSame = function(a, b) {
    
      return JSON.stringify(a) == JSON.stringify(b);
    }
    

    2) 使用PHP的内置日期函数和strtotime

    class DateUtil {
        function notLeapYear ($var) {
            return (date( 'L', strtotime( $var)) == "0");
        }
    }
    
        5
  •  0
  •   Tgr    14 年前
    • 从不重复 in
    • 您应该说明函数应该做什么;例如,数组比较应该是递归的吗?它应该使用严格的等价性吗?
    • 编写单元测试