多维数组,检查差异

时间:2013-03-19 16:13:28

标签: php arrays loops

我有2个阵列

Array
(
[0] => Array
    (
        [SKU] => 379
        [ProductName] => Wrap - Black
        [ProductSellingPrice] => 1.00
        [ProductQty] => 1
    )

[1] => Array
    (
        [SKU] => 3909
        [ProductName] => Wrap - Navy
        [ProductSellingPrice] => 0.00
        [ProductQty] => 1
    )

和第二:

Array
(
[0] => Array
    (
        [SKU] => 378
        [ProductName] => Wrap - White
        [ProductSellingPrice] => 1.00
        [ProductQty] => 1
    )

[1] => Array
    (
        [SKU] => 3909
        [ProductName] => Wrap - Navy
        [ProductSellingPrice] => 0.00
        [ProductQty] => 1
    )

我想循环遍历它们并返回键值之间的差异。

1 个答案:

答案 0 :(得分:2)

我刚才写了这篇文章来做你所要求的。 “compare_records”方法返回一个关联的更改数组,按字段名称键入。每个数组元素都是一个包含以下项的数组:

  1. from:original(left)value
  2. to:new(right)value
  3. message:log message
  4. 事件:将更改的性质描述为添加,删除或更改
  5. 这样称呼:

    $changes = db_tools::compare_records( $array_old, $array_new );
    

    class db_tools
    {
        public static $default_log_format = 'Field %1$s changed from "%2$s" to "%3$s"';
    
    /**
     * Returns a sorted list of keys from two arrays
     **/
        public static function get_keys( &$a, &$b )
        {
            $keys = array();
            foreach( $a as $k => $v ) $keys[$k] = 1;
            foreach( $b as $k => $v ) $keys[$k] = 1;
            ksort( $keys );
            return array_keys( $keys );
        } // get_keys
    
    
    /**
     * Compares values in two arrays and returns array of differences.
     *
     * Each  difference element is an associative array in the following format:
     *      'field/key name' => array(
     *          'from'      => "from_val"
     *        , 'to'        => "to_val"
     *        , 'message'   => "Loggable message"
     *        , 'event'     => "add" or "remove" or "change"
     *      )
     *
     * @param Array Original (old) array
     * @param Array Comparison (new) array
     * @param Array Special handling instructions -- allows you to ignore fields
     *              or truncate the logged value, as in:
     *              array(
     *                  'field_name' => 'ignore' // do not detect changes
     *                , 'field_2'    => 0 // detect changes, but do not describe them
     *                , 'field_3'    => 'from %2$s to %3s field %1$s was changed' // specially formatted log message
     *              );
     * @param Array List of keys to compare. If this is omitted, the list will be
     *              constructed from keys in the first two arguments.
     * @return Array
     * @author J.D. Pace
     * @since 2010/10/02
     **/
        public static function compare_records( &$a, &$b, $special = array(), $keyset = null )
        {
            $keys = ( empty( $keyset ) ? self::get_keys( $a, $b ) : $keyset );
            $diff = array();
    
            foreach( $keys as $k )
            {
                $_a = ( array_key_exists( $k, $a ) ? trim( $a[$k] ) : '' );
                $_b = ( array_key_exists( $k, $b ) ? trim( $b[$k] ) : '' );
    
                if( $_a != $_b )
                {
                    $fmt = &self::$default_log_format;
                    if( array_key_exists( $k, $special ) )
                    {
                        if( $special[$k] == 'ignore' )  continue;
    
                        if( $special[$k] == '0' )       $fmt = '%1$s changed';
                        else                            $fmt = &$instr;
    
                    }
                    $diff[$k] = array(
                        'from'      => $_a
                      , 'to'        => $_b
                      , 'message'   => sprintf( $fmt, $k, $_a, $_b )
                      , 'event'     => (
                            empty( $_a )
                            ? 'add'
                            : (
                                empty( $_b )
                                ? 'remove'
                                : 'change'
                            )
                        )
                    );
                }
            }
            return $diff;
        }
    
    /**
     * Applies new data from record b to record a according to options keyset
     * @param Array Destination Array
     * @param Array Source Array
     * @param Array Keys to apply. If this is omitted, record b will be copied
     *              into record a
     **/
        public static function update_record( &$a, &$b, $keyset = null )
        {
            $keys = ( empty( $keyset ) ? self::get_keys( $a, $b ) : $keyset );
            $updated = array();
            foreach( $keys as $k )
            {
                $a[$k] = ( empty( $b[$k] ) ? '' : $b[$k] );
            }
        }
    
    } // class db_tools