目录
引言
思路
实操
生成测试文件
分割文件
查找重复记录
完整代码
首页 后端开发 PHP问题 PHP如何在两个文件中找出相同的记录?

PHP如何在两个文件中找出相同的记录?

May 31, 2021 am 09:40 AM
php 海量数据 算法

本篇文章给大家介绍一下PHP如何在两个文件中找出相同的记录的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

PHP如何在两个文件中找出相同的记录?

引言

给定a,b两个文件, 分别有x,y行数据, 其中(x, y均大于10亿), 机器内存限制100M,该如何找出其中相同的记录?

思路

  • 处理该问题的困难主要是无法将这海量数据一次性读内内存中.

  • 一次性读不进内存中,那么是否可以考虑多次呢?如果可以,那么多次读入要怎么计算相同的值呢?

  • 我们可以用分治思想, 大而化小。相同字符串的值hash过后是相等的, 那么我们可以考虑使用hash取模, 将记录分散到n个文件中。这个n怎么取呢? PHP 100M内存,数组大约可以存100w的数据, 那么按a,b记录都只有10亿行来算, n至少要大于200。

  • 此时有200个文件,相同的记录肯定在同一个文件中,并且每个文件都可以全部读进内存。那么可以依次找出这200个文件中各自相同的记录,然后输出到同一个文件中,得到的最终结果就是a, b两个文件中相同的记录。

  • 找一个小文件中相同的记录很简单了吧,将每行记录作为hash表的key, 统计key的出现次数>=2就可以了。

实操

10亿各文件太大了,实操浪费时间,达到实践目的即可。

问题规模缩小为:  1M内存限制, a, b各有10w行记录, 内存限制可以用PHP的ini_set('memory_limit', '1M');来限制。

生成测试文件

生成随机数用于填充文件:

/**
 * 生成随机数填充文件
 * Author: ClassmateLin
 * Email: classmatelin.site@gmail.com
 * Site: https://www.classmatelin.top
 * @param string $filename 输出文件名
 * @param int $batch 按多少批次生成数据
 * @param int $batchSize 每批数据的大小
 */
function generate(string $filename, int $batch=1000, int $batchSize=10000)
{
    for ($i=0; $i<$batch; $i++) {
        $str = &#39;&#39;;
        for ($j=0; $j<$batchSize; $j++) {
            $str .= rand($batch, $batchSize) . PHP_EOL; // 生成随机数
        }
        file_put_contents($filename, $str, FILE_APPEND);  // 追加模式写入文件
    }
}

generate(&#39;a.txt&#39;, 10);
generate(&#39;b.txt&#39;, 10);
登录后复制

分割文件

  • a.txt, b.txt通过hash取模的方式分割到n个文件中.

/**
 * 用hash取模方式将文件分散到n个文件中
 * Author: ClassmateLin
 * Email: classmatelin.site@gmail.com
 * Site: https://www.classmatelin.top
 * @param string $filename 输入文件名
 * @param int $mod 按mod取模
 * @param string $dir 文件输出目录
 */
function spiltFile(string $filename, int $mod=20, string $dir=&#39;files&#39;)
{
    if (!is_dir($dir)){
        mkdir($dir);
    }

    $fp = fopen($filename, &#39;r&#39;);

    while (!feof($fp)){
        $line = fgets($fp);
        $n = crc32(hash(&#39;md5&#39;, $line)) % $mod; // hash取模
        $filepath = $dir . &#39;/&#39; . $n . &#39;.txt&#39;;  // 文件输出路径
        file_put_contents($filepath, $line, FILE_APPEND); // 追加模式写入文件
    }

    fclose($fp);
}

spiltFile(&#39;a.txt&#39;);
spiltFile(&#39;b.txt&#39;);
登录后复制
  • 执行splitFile函数, 得到如下图files目录的20个文件。

查找重复记录

现在需要查找20个文件中相同的记录, 其实也就是找一个文件中的相同记录,操作个20次。

  • 找一个文件中的相同记录:

/**
 * 查找一个文件中相同的记录输出到指定文件中
 * Author: ClassmateLin
 * Email: classmatelin.site@gmail.com
 * Site: https://www.classmatelin.top
 * @param string $inputFilename 输入文件路径
 * @param string $outputFilename 输出文件路径
 */
function search(string $inputFilename, $outputFilename=&#39;output.txt&#39;)
{
    $table = [];
    $fp = fopen($inputFilename, &#39;r&#39;);

    while (!feof($fp))
    {
        $line = fgets($fp);
        !isset($table[$line]) ? $table[$line] = 1 : $table[$line]++; // 未设置的值设1,否则自增
    }

    fclose($fp);

    foreach ($table as $line => $count)
    {
        if ($count >= 2){ // 出现大于2次的则是相同的记录,输出到指定文件中
            file_put_contents($outputFilename, $line, FILE_APPEND);
        }
    }
}
登录后复制
  • 找出所有文件相同记录:

/**
 * 从给定目录下文件中分别找出相同记录输出到指定文件中
 * Author: ClassmateLin
 * Email: classmatelin.site@gmail.com
 * Site: https://www.classmatelin.top
 * @param string $dirs 指定目录
 * @param string $outputFilename 输出文件路径
 */
function searchAll($dirs=&#39;files&#39;, $outputFilename=&#39;output.txt&#39;)
{
    $files = scandir($dirs);

    foreach ($files as $file)
    {
        $filepath = $dirs . &#39;/&#39; . $file;
        if (is_file($filepath)){
            search($filepath, $outputFilename);
        }
    }
}
登录后复制
  • 到这里已经解决了大文件处理的空间问题,那么时间问题该如何处理? 单机可通过利用CPU的多核心处理,不够的话通过多台服务器处理。

完整代码

登录后复制

推荐学习:php视频教程

以上是PHP如何在两个文件中找出相同的记录?的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南 适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 带来了多项新功能、安全性改进和性能改进,同时弃用和删除了大量功能。 本指南介绍了如何在 Ubuntu、Debian 或其衍生版本上安装 PHP 8.4 或升级到 PHP 8.4

CakePHP 日期和时间 CakePHP 日期和时间 Sep 10, 2024 pm 05:27 PM

为了在 cakephp4 中处理日期和时间,我们将使用可用的 FrozenTime 类。

CakePHP 使用数据库 CakePHP 使用数据库 Sep 10, 2024 pm 05:25 PM

在 CakePHP 中使用数据库非常容易。本章我们将了解CRUD(创建、读取、更新、删除)操作。

CakePHP 文件上传 CakePHP 文件上传 Sep 10, 2024 pm 05:27 PM

为了进行文件上传,我们将使用表单助手。这是文件上传的示例。

讨论 CakePHP 讨论 CakePHP Sep 10, 2024 pm 05:28 PM

CakePHP 是 PHP 的开源框架。它的目的是使应用程序的开发、部署和维护变得更加容易。 CakePHP 基于类似 MVC 的架构,功能强大且易于掌握。模型、视图和控制器 gu

CakePHP 创建验证器 CakePHP 创建验证器 Sep 10, 2024 pm 05:26 PM

可以通过在控制器中添加以下两行来创建验证器。

CakePHP 日志记录 CakePHP 日志记录 Sep 10, 2024 pm 05:26 PM

登录 CakePHP 是一项非常简单的任务。您只需使用一项功能即可。您可以记录任何后台进程(如 cronjob)的错误、异常、用户活动、用户采取的操作。在 CakePHP 中记录数据很容易。提供了 log() 函数

如何设置 Visual Studio Code (VS Code) 进行 PHP 开发 如何设置 Visual Studio Code (VS Code) 进行 PHP 开发 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也称为 VS Code,是一个免费的源代码编辑器 - 或集成开发环境 (IDE) - 可用于所有主要操作系统。 VS Code 拥有针对多种编程语言的大量扩展,可以轻松编写

See all articles