【问题标题】:HOw to correctly use array_diff()如何正确使用 array_diff()
【发布时间】:2014-04-22 23:40:43
【问题描述】:

我有以下代码:

$l1 = file($file1['tmp_name']);// get file 1 contents
$l2 = file($file2['tmp_name']);// get file 2 contents
$l3 = array_diff($l1, $l2);// create diff array

以下是文件: 文件 1:

6974527983
6974527984
6974527985

文件 2:

6974527983

$l3 应该是:

6974527984
6974527985

但是,它只是从文件 1 中吐出值:

6974527983
6974527984
6974527985

我设置对了吗?

更新 - 使用 print_r(),我验证了正在加载的文件被正确解析为数组: 文件 1 -

Array ( [0] => 6974527983 [1] => 6974527984 [2] => 6974527985 ) 1

文件 2 -

Array ( [0] => 6974527983 ) 1

所以我认为文本文件中的换行符没有任何问题。

【问题讨论】:

  • 乍一看似乎很好 - 我可以在这里在我的机器上复制您的预期结果。这让我想知道是否还有其他事情发生……这些上传的文件吗?深思熟虑:例如,如果第二个文件为空,您将获得结果。可能是第二个文件有问题?
  • 尝试使用 FILE_IGNORE_NEW_LINES 作为file() 调用的第二个参数
  • 文件已上传。这两个文件中都有数据,所以这不是问题。我只是尝试使用本地文件而不是上传,结果是一样的。
  • 感谢马克贝克。请查看我的更新。
  • 可能看起来像一个微不足道的问题,但为什么数字 1 在您的问题更新中跟随 print_r() 输出 - 它是一个错字还是实际出现在您的输出中?

标签: php array-difference


【解决方案1】:

如果每个数字都在新行上,您可以尝试通过换行符拆分每个文件并以这种方式比较数组。

$l1 = explode("\n", file($file1['tmp_name']));
$l2 = explode("\n", file($file2['tmp_name']));
$l3 = array_diff($l1, $l2);

【讨论】:

  • BTW - file($file_name) 创建一个数组。我认为您发布的代码会引发错误。
  • 啊,我的错 - 没有意识到它会为你将它放入一个数组中
【解决方案2】:

使用以下示例,您可以看到array_diff() 按预期工作:

$a = array(
    6974527983,
    6974527984,
    6974527985
);

$b = array(
    6974527983
);

var_dump(array_diff($a, $b));

输出:

array(2) {
  [1] =>
  int(6974527984)
  [2] =>
  int(6974527985)
}

这表明file($file2['tmp_name']) 是您的问题所在。试试:

var_dump(file($file2['tmp_name']));

检查文件的内容。

【讨论】:

  • 谢谢。我刚刚做了一个类似的实验,发现结果是find。问题是我在 file() 调用后检查了数组,所有数据都在那里。
  • 我刚刚尝试了 var_dump 并得到:array(1) { [0]=> string(1) "2" } 这是来自 var_dump(array_diff($l1, $l2)) 的转储: array(3) { [0]=> string(3) "1 " [1]=> string(3) "2 " [2]=> string(1) "3" } 我不习惯 var_dump ,但是这个输出看起来很奇怪,里面有'string(3)'。
  • string(3) 因为文件将不会删除行尾。您可以删除评论并将 var_dumps 添加到问题中吗?
【解决方案3】:

好的,我会发布一个答案,因为我认为这会解决您的问题。

在不了解文件结构的情况下,我们只能假设行尾可能存在问题。有三种可能的行尾:

  1. Unix:\n
  2. 窗口:\r\n
  3. 经典mac:\r

我在这里看到两种可能的情况:

  1. 每个文件的行尾都不同
  2. 两个文件中的行结尾都是\r(经典mac)

正如 Mark Ba​​ker 所指出的,您应该使用 FILE_IGNORE_NEW_LINES 标志作为每个 file() 调用的第二个参数。就我在这里快速试验的结果而言,如果一个文件有 Unix 而另一个文件有 Windows 行尾,这应该可以解决问题。

但是,在至少一个文件有 '\r' 行结尾的情况下,它似乎不能很好地处理。在这种情况下,有一个 ini 设置可能会有所帮助:

ini_set('auto_detect_line_endings', true);

咨询auto_detect_line_endings的文档:

打开后,PHP 将检查 fgets() 和 file() 读取的数据,看它是否使用 Unix、MS-Dos 或 Macintosh 行结束约定。

这使 PHP 可以与 Macintosh 系统互操作,但默认为关闭,因为在检测第一行的 EOL 约定时性能损失非常小,而且因为人们在 Unix 系统下使用回车作为项目分隔符会体验不向后兼容的行为。

所以,TL;DR:调试你的行尾以确保你知道发生了什么(使用filehexdump 或类似的),并使用auto_detect_line_endingsFILE_IGNORE_NEW_LINES 的组合。

希望这会有所帮助:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 2013-06-03
    • 2022-01-26
    相关资源
    最近更新 更多