为什么 array_diff_uassoc 比较值不匹配的键

2023-12-28

我刚刚读过那个问题 https://stackoverflow.com/q/9458652/576767关于奇怪的 php 行为,尽管我可以研究更多,但我还远远无法理解它。

我假设读者已经阅读了原始问题并且知道OP的代码块和示例,但简而言之,OP正在尝试比较这两个数组,虽然结果很好,但比较函数似乎被不规则地调用:

$chomik = new chomik('a');
$a = array(5, $chomik, $chomik, $chomik);
$b = array($chomik, 'b', 'c', 'd');
array_diff_uassoc($a, $b, 'compare');

文档 http://php.net/manual/en/function.array-diff-uassoc.php有点晦涩......但它确实指出:

如果第一个参数被认为是,则比较函数必须返回小于、等于或大于零的整数分别小于、等于或大于第二。

据我了解,这意味着compare()函数应该更像这样:

function compare($a, $b) {
    echo("$a : $b<br/>");
    if($a === $b) return 0;
    else if ($a > $b) return 1;
    else return -1;
}

然而,这仍然给出了非常奇怪的结果,甚至有更多的“重复”



1 : 0
1 : 2
3 : 1
2 : 1
3 : 2
1 : 0
1 : 2
3 : 1
2 : 1
3 : 2
0 : 0
1 : 0
1 : 1
2 : 0
2 : 1
2 : 2
3 : 0
3 : 1
3 : 2
3 : 3
  

面对诸多质疑,我读取compat php函数 https://pear.php.net/reference/PHP_Compat-latest/__filesource/fsource_PHP_Compat__PHP_Compat-1.6.0a3CompatFunctionarray_diff_uassoc.php.html,检查实际发生的部分很有趣:

foreach ($args[0] as $k => $v) {
    for ($i = 1; $i < $array_count; $i++) {
        foreach ($args[$i] as $kk => $vv) {
            if ($v == $vv) { // compare keys only if value are the same
                $compare = call_user_func_array($compare_func, array($k, $kk));
                if ($compare == 0) {
                    continue 3; // value should not be added to the result
                }
            }
        }
    }
    $result[$k] = $v;
}

这是实际来源 https://github.com/php/php-src/blob/master/ext/standard/array.c#L3938 (per comment https://stackoverflow.com/questions/29421414/why-does-array-diff-uassoc-compares-keys-whose-value-do-not-match#comment47016778_29422485)

这段代码执行比较函数的方式不应该输出我们看到的结果。 Foreach 无法在键中来回移动(据我所知???),这里第一个键的顺序似乎就是这种情况:



1 : 2
3 : 1
2 : 1
  

此外,如果值不匹配,它不应该检查键,那么为什么要检查所有这些:



1 : 2
3 : 1
2 : 1
3 : 2
etc...
  

源码中最上面的foreach()怎么能通过key来回循环呢?!

为什么值不匹配的键仍然进行比较?

foreach 循环实际上是否继续执行,即使它们已经执行过continued?

这是并发的一个例子吗?可以以某种方式启动 call_user_func_array 并实际执行echo("$a : $b<br/>");比较函数的顺序与它们“启动”的顺序不一样?


我相信你已经指出了一个错误,我的朋友。我刚刚运行了您引用的问题中的代码,果然,它比较了不同值的键。不过,我想测试一下源代码本身是否包含错误,所以我添加了官方源代码array_diff_uassoc这是他的代码的顶部,在我自己的命名空间内:

<?php

namespace mine;

// Code obtained from https://pear.php.net/reference/PHP_Compat-latest/__filesource/fsource_PHP_Compat__PHP_Compat-1.6.0a3CompatFunctionarray_diff_uassoc.php.html

function array_diff_uassoc()


{

    // Sanity check

    $args = func_get_args();

    if (count($args) < 3) {

        user_error('Wrong parameter count for array_diff_uassoc()', E_USER_WARNING);

        return;

    }



    // Get compare function

    $compare_func = array_pop($args);

    if (!is_callable($compare_func)) {

        if (is_array($compare_func)) {

            $compare_func = $compare_func[0] . '::' . $compare_func[1];

        }

        user_error('array_diff_uassoc() Not a valid callback ' .

            $compare_func, E_USER_WARNING);

        return;

    }



    // Check arrays

    $array_count = count($args);

    for ($i = 0; $i !== $array_count; $i++) {

        if (!is_array($args[$i])) {

            user_error('array_diff_uassoc() Argument #' .

                ($i + 1) . ' is not an array', E_USER_WARNING);

            return;

        }

    }



    // Compare entries

    $result = array();

    foreach ($args[0] as $k => $v) {

        for ($i = 1; $i < $array_count; $i++) {

            foreach ($args[$i] as $kk => $vv) {

                if ($v == $vv) {

               //   echo ("$v\n");
                    // echo ("$vv\n");
               //   echo ("$k\n");
                    // echo ("$kk\n");
                    // die();

                    $compare = call_user_func_array($compare_func, array($k, $kk));

                    if ($compare == 0) {

                        continue 3;

                    }

                }

            }

        }



        $result[$k] = $v;

    }

    return $result;

}

class chomik {

    public $state = 'normal';
    public $name = 'no name';

    public function __construct($name) {
        $this->name = $name;
    }

    public function __toString() {
        return $this->name . " - " . $this->state;
    }
}

function compare($a, $b) {
    echo("$a : $b\n");
    if($a != $b) {
        return 0;
    }
    else return 1;
}

$chomik = new chomik('a');
$a = array(5, $chomik, $chomik, $chomik);
$b = array($chomik, 'b', 'c', 'd');
array_diff_uassoc($a, $b, 'mine\compare');

这次,它只比较键中是否有相等的值:

1 : 0
2 : 0
3 : 0

奇怪吧?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 array_diff_uassoc 比较值不匹配的键 的相关文章

  • Laravel 注册成功后如何重定向到上一页?

    现在redirectTo被设定为 home 我想知道如何重定向到上一页 我尝试使用 protected redirectTo URL previous 但我得到解析错误 期待 or 解决这个问题的最佳解决方案是什么 我想我需要重写 redi
  • 使用 ImapMailbox.php 按日期对 Imap 邮箱进行排序

    我有一个客户支持系统 它会在收到电子邮件时创建电子邮件 我曾经使用后缀和特殊配置来获取电子邮件以添加额外的功能 例如 我想包含从电子邮件发送的附件 系统不会执行此操作 而是创建一封带有主题的电子邮件 因此我可以通过匹配主题来包含附件 我使用
  • Ajax 与 chrome 扩展

    我将 url 发送到 chrome 扩展中的 php 文件 并需要获得响应 但不起作用 清单 json name Get pages source version 1 0 manifest version 2 description Get
  • PHP 自定义会话处理程序问题 (PHP 7.1)

    我刚刚在计算机上从 PHP 7 0 迁移到 PHP 7 1 当前版本的 WAMP 的全新 全新安装 它似乎破坏了自定义会话处理程序中的某些内容 该处理程序应该将会话保存到数据库而不是使用文件系统 自定义处理程序类是 class db ses
  • PHP 函数 iconv 字符编码从 iso-8859-1 到 utf-8

    我正在尝试将字符串从 iso 8859 1 转换为 utf 8 但是当我找到这两个字符 和 时 函数返回 一个字符 是一个里面有两个数字的正方形 我该如何解决这个问题 我认为您正在寻找的编码是Windows 代码页 1252 http en
  • WooCommerce 自定义字段 - 多选

    我在 WooCommerce 的结账页面添加额外的字段 我可以添加文本框等基本字段 但需要添加一个 多 选择框 用户可以在其中选择多个项目 我已经弄清楚如何通过代码添加选择框 如下所示 add action woocommerce afte
  • PHP正则表达式替换链接url

    我需要添加href 之前http 如果这http 不遵循href or src 以下代码部分有效 部分意味着它考虑 a href 只但不src a s i a href target blank gt 0 a str 预先感谢各位的回复 s
  • 数组数据标准化

    我有一个表示强度 黑到白 的值数组 在 1 0 和 1 0 之间 我需要一种方法将双精度值从 1 0 到 1 0 映射到 0 到 255 并返回 更概括地说 我有一个数据数组 我需要将数据的最小值和最大值映射到提供的最小值和最大值 基本结构
  • 在 Perl 中,如何制作数组的深层复制? [复制]

    这个问题在这里已经有答案了 可能的重复 在 Perl 中制作数据结构深层复制的最佳方法是什么 https stackoverflow com questions 388187 whats the best way to make a dee
  • PHP 多个 Ajax 请求:第一个请求阻止第二个请求

    我在一页上有 2 个 ajax 请求 我运行了第一个请求并单独启动了第二个请求 但第二个在第一个运行后停止工作 第一次结束后继续 第一个请求需要很长时间 大约 30 60 秒 此时我需要第二个请求来显示日志第一个请求发生的情况 我尝试使用
  • 使用活动目录对 Intranet 站点上的用户进行身份验证

    我建立了一个 内联网 站点 它有自己的登录系统 用户注册为新用户 并使用其上的用户名 密码登录该站点 但是 现在我想扩展它 让 Intranet 站点使用现有的 ActiveDirectory 进行身份验证 这就是我正在寻找的 前进 当用户
  • 如何使用 PATCH 更新简单的数据库字段?

    我是 php 和 API 的新手 我正在尝试学习这些方法 但我无法执行 PATCH 或 PUT 来更新我的简单 mysql 数据库 我使用了以下代码 if isset PATCH con mysqli connect localhost r
  • 从 PHP 启动守护进程

    对于网站 我需要能够启动和停止守护进程 我目前正在做的是 exec sudo etc init d daemonToStart start 守护进程已启动 但 Apache PHP 挂起 做一个ps aux透露sudo它本身变成了僵尸进程
  • php - 重定向ajax请求[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何在 php wordpress 中重定向 ajax 请求 I tried header Location http redirect
  • PHP + MySQL 队列

    我需要一个充当队列的简单表 我的 MySQL 服务器限制是我不能使用 InnoDB 表 只能使用 MyISAM 客户 工人将同时工作 他们每次都需要接受不同的工作 我的想法是执行以下操作 伪代码 job lt SELECT FROM que
  • 什么是 PHP session_start()

    它是否基于 cookie 启动当前会话 从 PHP 网站上得到的 PHP如何控制会话 如果我在用户打开我的登录页面时启动会话 我什至可以使用该会话做什么 我可以使用当前会话来获取有关登录用户的信息吗 PHP 会话系统允许您将数据安全地存储在
  • 使用排序函数按 NSDates 对数组进行排序[重复]

    这个问题在这里已经有答案了 我有一个名为的模型类Event import Foundation import MapKit public class Event let id Int var title String let status
  • 如何在没有 SSH 和 CLI 访问生产的情况下部署 symfony 项目 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 大多数托管提供商仅具有 FTP 访问权限 是否可以 常见地进行 symfony 项目 3 x 或 4 x 的本地安装 然后通过 FTP 上
  • 在 Elasticsearch php API 中使用多种类型或索引

    我想使用查询多种类型和索引Elasticsearch PHP API 但我不知道怎么办 我应该将类型和索引的数组传递给 params params index index array of indices params type types
  • SimpleXML 返回空数组

    我正在尝试使用 Google Maps API 和 PHP SimpleXML 获取城市的纬度和经度 我尝试这样做 xml simplexml load file http maps googleapis com maps api geoc

随机推荐