PHP 从多维数组创建消息线程的多维数组 (IMAP)

2023-11-25

我的问题如下:

如果你往下看,你会看到有一个带有消息 ID 的数据结构,然后是包含消息详细信息的最终数据结构,这些详细信息应该从imap_fetch_overview。消息 ID 来自imap_thread。问题是它没有将电子邮件详细信息放在消息 ID 所在的位置。

这是我的数据结构:

[5] => Array
    (
        [0] => 5
        [1] => 9
    )

[10] => Array
    (
        [0] => 10
        [1] => 11
    )

我想要的是:

[5] => Array
    (
        [0] => messageDetails for id 5
        [1] => messageDetails for id 9
    )

[10] => Array
    (
        [0] => messageDetails for id 10
        [1] => messageDetails for id 11
    )

这是我迄今为止的代码:

$emails = imap_fetch_overview($imap, implode(',',$ids));

// root is the array index position of the threads message, such as 5 or 10
foreach($threads as $root => $messages){

    // id is the id being given to us from `imap_thread`
    foreach($message as $key => $id){

      foreach($emails as $index => $email){

         if($id === $email->msgno){
             $threads[$root][$key] = $email;
             break;
          }
      }
    }
 }

以下是其中一封 $email 的打印输出:

    [0] => stdClass Object
    (
        [subject] => Cloud Storage Dump
        [from] => Josh Doe
        [to] => [email protected]
        [date] => Mon, 21 Jan 2013 23:18:00 -0500
        [message_id] => <[email protected]>
        [size] => 2559
        [uid] => 5
        [msgno] => 5
        [recent] => 0
        [flagged] => 0
        [answered] => 1
        [deleted] => 0
        [seen] => 0
        [draft] => 0
        [udate] => 1358828308
    )

如果您注意到的话,msgno 是 5,这与$id,因此从技术上讲,数据应该填充到最终的数据结构中。

此外,这似乎是处理此问题的低效方法。

如果您需要任何其他说明,请告诉我。

更新代码

这段代码是我在 php api 上找到的代码和我的一些修复的组合。我认为有问题的仍然是$root.

$addedEmails = array();
$thread = imap_thread($imap);
foreach ($thread as $i => $messageId) { 
    list($sequence, $type) = explode('.', $i); 
    //if type is not num or messageId is 0 or (start of a new thread and no next) or is already set 
   if($type != 'num' || $messageId == 0 || ($root == 0 && $thread[$sequence.'.next'] == 0) || isset($rootValues[$messageId])) { 
    //ignore it 
    continue; 
} 

if(in_array($messageId, $addedEmails)){
    continue;
}
array_push($addedEmails,$messageId);

//if this is the start of a new thread 
if($root == 0) { 
    //set root 
    $root = $messageId; 
} 

//at this point this will be part of a thread 
//let's remember the root for this email 
$rootValues[$messageId] = $root; 

//if there is no next 
if($thread[$sequence.'.next'] == 0) { 
    //reset root 
    $root = 0; 
    } 
  }
$ids=array();
$threads = array();
foreach($rootValues as $id => $root){
    if(!array_key_exists($root,$threads)){
        $threads[$root] = array();
    }
    if(!in_array($id,$threads[$root])){
        $threads[$root][] = $id;
       $ids[]=$id;
    }
 }
 $emails = imap_fetch_overview($imap, implode(',', array_keys($rootValues)));

 $keys = array();
 foreach($emails as $k => $email)
 {
$keys[$email->msgno] = $k;
 }

 $threads = array_map(function($thread) use($emails, $keys)
{
// Iterate emails in these threads
return array_map(function($msgno) use($emails, $keys)
{
    // Swap the msgno with the email details
    return $emails[$keys[$msgno]];

}, $thread);
}, $threads);

请记住,在 php 中,无论您使用什么函数,它最终都会转换为某种循环。 不过,您可以采取一些步骤来提高效率,这些步骤在 PHP 5.5 和 5.3/5.4 中是不同的。

PHP 5.3/5.4方式

最有效的方法是将函数拆分为两个单独的步骤。 第一步,您将为电子邮件列表生成键映射。

$keys = array();
foreach($emails as $k => $email)
{
    $keys[$email->msgno] = $k;
}

在第二步中,您迭代多维 $threads 中的所有值并将它们替换为电子邮件详细信息:

// Iterate threads
$threads = array_map(function($thread) use($emails, $keys)
{
    // Iterate emails in these threads
    return array_map(function($msgno) use($emails, $keys)
    {
        // Swap the msgno with the email details
        return $emails[$keys[$msgno]];

    }, $thread);

}, $threads);

概念证明:http://pastebin.com/rp5QFN4J

关键词解释use在匿名函数中:

为了使用父作用域中定义的变量,可以使用以下命令将变量从父作用域导入到闭包作用域中:use ()关键词。尽管它是在 PHP 5.3 中引入的,但尚未在官方 PHP 手册中记录。这里只有 php 的 wiki 上的草稿文档https://wiki.php.net/rfc/closures#userland_perspective

PHP 5.5

此版本中的一项新功能使您可以使用生成器,它的内存指纹要小得多,因此效率更高。

关键词解释yield在发电机中:

生成器函数的核心是yield关键词。从最简单的形式来看,yield 语句看起来很像 return 语句,不同之处在于,yield 不是停止执行函数并返回,而是为循环生成器的代码提供一个值,并暂停生成器函数的执行。

第一步:

function genetateKeyMap($emails)
{
    foreach($emails as $k => $email)
    {
        // Yielding key => value pair to result set
        yield $email->msgno => $k;
    }
};
$keys = iterator_to_array(genetateKeyMap($emails));

第二步:

function updateThreads($emails, $threads, $keys)
{
    foreach($threads as $thread)
    {
        $array = array();

        // Create a set of detailed emails
        foreach($thread as $msgno)
        {
            $array[] = $emails[$keys[$msgno]];
        }

        // Yielding array to result set
        yield $array;
    }
};
$threads = iterator_to_array(updateThreads($emails, $threads, $keys));

关于生成器返回的值的几句话:

生成器返回一个对象,该对象是 SPL Iterator 的实例,因此它需要使用 iterator_to_array() 才能将其转换为与代码所期望的完全相同的数组结构。您不需要这样做,但需要在生成器函数之后更新代码,这可能会更有效。

概念证明:http://pastebin.com/9Z4pftBH

测试性能:

我生成了 7000 个线程的列表,每个线程有 5 条消息,并测试了每种方法的性能(5 次测试的平均值):

                   Takes:       Memory used:
                   ----------------------------
3x foreach():      2.8s              5.2 MB
PHP 5.3/5.4 way    0.061s            2.7 MB
PHP 5.5 way        0.036s            2.7 MB

尽管您的计算机/服务器上的结果可能有所不同,但概述表明 2 步方法比使用 3 个 foreach 循环快大约 45-77 倍

测试脚本:http://pastebin.com/M40hf0x7

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

PHP 从多维数组创建消息线程的多维数组 (IMAP) 的相关文章

  • 运行没有扩展名的 PHP 页面

    我想在 apache Web 服务器上运行我的 PHP 网页 而不需要 php扩大 所以我添加了以下代码 RewriteEngine on RewriteBase Rewritecond REQUEST URI NC RewriteRule
  • 使用 php 获取当前月份的最后 3 个月

    我想获取当前月份最近 3 个月的名称 例如当前月份是八月 所以 我想要六月 七月 八月这样的数据 我已经尝试过这段代码echo date F strtotime 3 months 它只返回六月 如何使用 php 获取当前月份的最后 3 个月
  • 在值中包含换行符

    我有一个 Word 模板 其中 php 代码中定义了值 在PHP代码中 document gt setValue Value1 value1 在word模板中 Value1 如何将包含两个值之间的断线的值包含在单词的值中 Replace n
  • PHP - 获取base64图像字符串解码并保存为jpg(生成空图像)

    嗨 我实际上是通过 ajax 发送一个 base64 图像字符串到一个 php 脚本 该脚本只是解码字符串并将内容保存为 jpg 文件 但结果是一张空图像 这怎么可能 PHP脚本 uploadedPhotos array photo 1 p
  • Yii2 异常:ApcCache 需要加载 PHP apc 扩展

    在高级模板前端的主配置中配置缓存组件时 我收到异常 在我的 php ini 上启用了扩展 rsults 如何解决此问题 前端 config main php cache gt class gt yii caching ApcCache ke
  • PHP 或 WAMP 不确定是什么

    我已经安装了 WAMP 服务器 2 0 PHP 5 4 3 安装WAMP后我已经重新启动了所有服务并且可以打开 phpinfo 显示良好 phpmyadmin 它也显示得很好 我可以使用数据库 然而 当在 Chrome 中运行简单的 php
  • PHP 绑定“bigint”数据类型(MySQLi 准备好的语句)

    studentId 57004542323382 companyOfferId 7 sql INSERT INTO studentPlacement companyOfferId studentId VALUES if stmt db gt
  • zip 文件的校验和

    我目前正在开发一个工具 它上传一组文件 然后使用 md5 校验和将文件与上一批上传的文件进行比较 并告诉您哪些文件已更改 对于常规文件 这工作正常 但某些上传的文件是 zip 存档 即使其中的文件相同 它们几乎总是会发生变化 有没有一种方法
  • 在字符串中间添加一个字符

    可能有一个简单的解决方案可以解决这个问题 但会引起面部表情 我将时间存储为 4 个字符长的字符串 即 1300 我试图将该字符串显示为 13 00 我觉得必须有一个比我现在正在做的更优雅的解决方案 我目前有 startTime get fi
  • 将 Google 信任徽章添加到 Magento

    我正在尝试将 Google Trust Badge 添加到我的 magento 商店 我尝试在 Magento 网站上搜索扩展程序 但找不到 我是否需要将以下代码粘贴到产品和结账页面 还是必须对其进行更改 如果有人能引导我走向正确的方向 我
  • PHP Solr PECL 扩展安装

    我已经使用命令安装了 pecl solr pecl install solr 和梨使用 wget http pear php net go pear phar php go pear phar 重启Apache后 我仍然收到错误 Fatal
  • WordPress 分页自定义帖子类型

    我有一个名为 新闻 的页面 使用页面模板page newslist php 它应该显示来自自定义帖子类型 也称为新闻 的帖子 我意识到两者具有相同的名称会导致问题 因此在注册自定义帖子类型时 我进行了重写以将其与页面区分开来 rewrite
  • 强制 Composer 下载 git repo 而不是 zip

    我对作曲家有一些问题 require php gt 5 3 2 kriswallsmith buzz 0 7 Repo https github com kriswallsmith Buzz tree v0 7 https github c
  • MySQL PHP邮政编码比较具体距离

    我试图找出比较一个邮政编码 用户提供的 和一大堆其他邮政编码 现在大约有 200 个邮政编码 之间的距离的最有效方法 相对于加载时间 但它会随着时间的推移而增加 我不需要任何精确的东西 只是在球场上 我下载了整个美国的邮政编码 csv 文件
  • 如何在 OS X 上使用 OpenSSL 1.0.1 编译 PHP 5.5.19

    我已经安装了 OpenSSL 1 0 1j usr local ssl现在我尝试使用此版本的 OpenSSL 编译 PHP 5 5 19 这是我的配置过程 export CFLAGS arch x86 64 export CXXFLAGS
  • MVC 模式中的验证层

    验证模型将使用的数据的最佳位置在哪里 例如 考虑登记表 我们有一些来自注册表的数据 那么验证这些数据的最佳位置在哪里 我们应该通过 if 语句或特殊的验证器类来检查每个数据 这意味着大量的编码 所以我想了解在哪里可以做到这一点 在控制器中
  • suhosin.mt_srand.ignore 在 PHP 中一致洗牌数组的解决方法?

    我有一个 PHP 脚本 需要随机化一个具有一致结果的数组 这样它就可以向用户呈现前几个项目 然后如果他们愿意 他们可以从同一个打乱的集合中提取更多结果 我目前使用的是这个 基于我相信的 Fisher Yates 算法 function sh
  • 保存多对多关系,同步/附加不存在?

    我有以下两个多对多关系的模型 use Illuminate Database Eloquent Model class Permission extends Model The database table used by the mode
  • Laravel $request->file() 返回 null

    尝试在后端使用 Laravel 上传文件时遇到问题 Issue Laravel request gt file 方法返回 null Setup 我使用以下方法构建了一个 AJAX 请求超级代理人 https github com visio
  • 为什么我的会话仍然存在?

    我一定很愚蠢 因为似乎一件相当明显的事情现在让我完全困惑 我有一个会议 ie SESSION handbag id 在某个时刻 我需要彻底终止这个会话 ie at the start of the page session start el

随机推荐

  • 在命令行(终端)上使用 R 脚本的最佳方式是什么?

    使用 R 脚本从命令行进行简单绘图非常方便 然而 从 bash 脚本运行 R 一点也不方便 理想的可能是这样的 path to R or usr bin env R 但我没能让其中任何一个发挥作用 另一种选择是将脚本纯粹保留在 R 中 例如
  • 如何使用 R 从 dropbox 下载文件(任何形式)

    I tried download file https www dropbox com s r3asyvybozbizrm Himalayas jpg destfile 1 jpg method auto 但它返回该页面的 HTML 源代码
  • mongodb是否具有关系型数据库中的trigger、procedure等属性?

    正如标题所示 包括 Map Reduce 框架 如果我想在插入记录之前触发一个事件来运行一致性检查或安全操作 我该如何使用 MongoDB 来做到这一点 MongoDB 不支持触 发器 但人们已经围绕它们创建了解决方案 主要使用 oplog
  • Java中超类引用无法调用子类方法

    我对Java的多态性有一个基本的怀疑 我已将下面的代码写入一个名为 AnimalTestDrive java 的文件中 根据我的说法 下面的代码应该特别适用于粗体行 但不幸的是它不是 你能解释一下为什么吗 我给出了以下错误 class Do
  • 在 Chart.js 段中嵌入唯一标识符?

    我想通过允许用户双击切片进行向下钻取来使饼图具有交互性 我相信做到这一点的方法是在画布上创建一个 onclick 处理程序 并使用getSegmentsAtEvent 以确定单击了哪个切片 调用返回的段数据getSegmentsAtEven
  • 缓慢的“属性获取”和“函数”过程

    我遇到了一个令人讨厌的 VBA 错误 它使得Property Get过程调用真的很慢 这很可能是由于最近的 Office 更新 我有 Office365 造成的 它仅影响 32 位 CPU 上的 Excel The bug 考虑一个名为Cl
  • 变更数据捕获或变更跟踪 - 与传统审计跟踪表相同吗?

    在我深入研究 Microsoft 文档的深渊之前 我想知道有变更数据捕获和变更跟踪经验的人是否知道其中之一或两者是否可以用来取代传统的 审计追踪表副本 真实 table 原始表的所有字段 加上日期 时间 用户 ID 和 DML 动作字段 插
  • 您能推荐 PHP 性能分析工具吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 谁能推荐一些有用的 PHP
  • 非静态成员函数的 decltype 格式是否错误?

    我不确定是否完全理解 dcl type 4 3 对于一个表达式e 表示的类型decltype e 定义如下 4 3 否则 如果e是不带括号的 id 表达式或不带括号的类成员访问 decltype e 是命名实体的类型e 如果没有这样的实体
  • 如何在 Java 中使用正则表达式查找重复字符?

    谁能给我一个 Java 正则表达式来识别字符串中的重复字符 我只寻找立即重复的字符 它们可以是字母或数字 Example abcccde abcde Try w 1 The w匹配任何单词字符 字母 数字或下划线 并且 1 匹配第一组括号中
  • Javascript:未定义为函数参数

    On this page 它显示了一些示例代码 包含以下行 var Subject function window undefined 是什么undefined作为函数参数 这用于防止覆盖值undefined在非严格模式下 在非严格模式下
  • SendMessage,什么时候使用KEYDOWN,SYSKEYDOWN等?

    我正在编写一个应用程序 使用以下命令将击键发送到另一个应用程序SendMessage DllImport user32 dll public static extern int SendMessage IntPtr hWnd int Msg
  • C++11 lambda 到函数指针

    我开始使用 C 11 lambda 开发应用程序 并且需要将某些类型转换为函数指针 这在 GCC 4 6 0 中完美运行 void test puts Test test 我的问题是当我需要在 lambda 中使用函数或方法局部变量时 co
  • PrintWriter 和 DataOutputStream 有什么区别?

    我正在开发一个 Android 聊天室应用程序 我阅读了不同的教程 有些使用PrintWriter发送数据 有些使用DataOutputStream 这两者有什么区别 哪一个更适合聊天应用程序 来自java文档 A 数据输出流允许应用程序以
  • Django 中的 related_name 和 related_query_name 是什么?

    我对 django 框架中的代码有一个问题related name 和 related query name在 Django 中 请django专家解释一下django中的 related name 代码如下 相关名称 相关名称 Djang
  • 适合多个客户的 Android 构建配置

    我有一个 Android 应用程序需要交付给多个客户 对于每个客户 我都有不同的图形和配置 XML 文件 其中指定了功能和 URL 在构建时 我们应该能够指定应为其构建应用程序的客户 然后 应将适合指定客户端的资源 例如图像和运行时配置 内
  • 仅当字段不为 Null 时才验证

    I use JSR303 Spring Validation我有以下内容 Digits fraction 0 integer 15 private String tpMobile 验证说Must be number between 10 1
  • 如何在 Java 中解密 sha1 加密的字符串

    是否有可能解密一些之前用 Java 中的 SHA 1 算法加密的字符串 SHA1 是加密哈希函数 重点是您无法撤消它 如果可以反转哈希值 找到给定哈希值的输入 那么它就没有用处 如果您需要加密某些内容然后解密它 您应该使用加密功能 like
  • 如何将参数 n 传递给 printf("%nd", some_int);

    我们都知道在基于 C 的语言中 printf 11d some int 意味着在 11 个字符字段内右对齐 但是如果我想用动态变量替换这里的常量 11 我该怎么办 您可以使用 字符在其自己的参数中指定字段宽度 printf d some w
  • PHP 从多维数组创建消息线程的多维数组 (IMAP)

    我的问题如下 如果你往下看 你会看到有一个带有消息 ID 的数据结构 然后是包含消息详细信息的最终数据结构 这些详细信息应该从imap fetch overview 消息 ID 来自imap thread 问题是它没有将电子邮件详细信息放在