如何在没有嵌套的foreach循环的情况下基于键值对组合两个多维数组?

时间:2018-10-26 15:29:11

标签: php arrays loops multidimensional-array foreach

我有2个数组,$fileArr$noteArr

$fileArr是文件列表。一个文件可以链接到多个故事。因此,在此$fileArr中,您看到的是我需要列出的每个故事的所有文件。请注意,CAR.jpg([processId]=>111)已链接到[storyId]=>1[storyId]=>2。因此,CAR.jpg将被列出两次。

我想记下$noteArr的所有笔记,并通过匹配$fileArr]将它们放入[processId。因此,每个CAR.jpg实例将具有2个注释,而TRUCK.jpg将没有任何注释。

我当前的$ fileArr

Array
(
[0] => Array
    (
        [fileName] => CAR.jpg
        [processId] => 111
        [storyId] => 1
    )

[1] => Array
    (
        [fileName] => CAR.jpg
        [processId] => 111
        [storyId] => 2
    )

[2] => Array
    (
        [fileName] => TRUCK.jpg
        [processId] => 222
        [storyId] => 3
    )
)

我当前的$ noteArr

Array
(
[0] => Array
    (
        [noteId] => 50
        [note] => this is a note
        [processId] => 111
    )

[1] => Array
    (
        [noteId] => 51
        [note] => and this is also a note
        [processId] => 111
    )

)

我想要的新数组,其中的注释通过匹配processId放置在文件下

Array
(
[0] => Array
    (
        [fileName] => CAR.jpg
        [processId] => 111
        [storyId] => 1
        [notes] => Array
              (
                    [50] => Array
                          (
                                [noteId] => 50
                                [note] => this is a note
                                [processId] => 111
                          )
                    [51] => Array
                          (
                                [noteId] => 51
                                [note] => and this is also a note
                                [processId] => 111
                          )
              )
    )

[1] => Array
    (
        [fileName] => CAR.jpg
        [processId] => 111
        [storyId] => 2
        [notes] => Array
              (
                    [50] => Array
                          (
                                [noteId] => 50
                                [note] => this is a note
                                [processId] => 111
                          )
                    [51] => Array
                          (
                                [noteId] => 51
                                [note] => and this is also a note
                                [processId] => 111
                          )
              )
    )

[2] => Array
    (
        [fileName] => TRUCK.jpg
        [processId] => 222
        [storyId] => 3
    )
)

我可以通过下面编写的代码来完成此操作,但是不想在循环中使用循环。还有另一种方法可以实现这一目标吗?

我当前的代码(循环内循环)

$newArr = array();

$i = 0;
foreach($fileArr as $file){
    $newArr[$i] = $file;

    if(count($noteArr)>0){
        foreach($noteArr as $note){
            if($file['processId']==$note['processId']){
                $newArr[$i]['notes'][$note['id']] = $note;
            }
        }
    }
    $i++;
}

4 个答案:

答案 0 :(得分:1)

如果您想删除嵌套循环以减少执行时间,则可以通过两次通过来完成

// save items of noteArr for each processId
$temp = [];
foreach($noteArr as $k => $note) {
   $temp[$note['processId']][] = $note;
}

// and add saved sub-arrays to the source one
$newArr = [];
$i = 0;
foreach($fileArr as $file){
    $newArr[$i] = $file;
    if(isset($temp[$file['processId']])) 
         $newArr[$i]['notes'] = $temp[$file['processId'];
    $i++;
}

答案 1 :(得分:0)

没有嵌套循环,您可以创建一个函数并通过引用传递:

function addNote(array &$array, array $notes)
{
    $array['notes'] = [];
    foreach ($notes as $note)
    {
        if ($note['processId'] == $array['processId']) {
            $array['notes'][] = $note;
        }
    }
    return $array;
}

foreach ($fileArr as &$file) {
    addNote($file, $notes);
}

var_dump($fileArr);

看到它在这里https://3v4l.org/u37UL

答案 2 :(得分:0)

嗨,我快速浏览一下如何解决您的问题。不幸的是,它最终陷入了嵌套循环,但是我不需要循环任何项目(在您的解决方案中,您循环每个文件的所有注释)两次。

function sortProcessId($a, $b)
{
    return $a['processId'] <=> $b['processId'];
}

$newArr = [];

usort($fileArr, 'sortProcessId');
usort($noteArr, 'sortProcessId');
rsort($noteArr);
$currentProcessId = 0;
$currentNote = array_pop($noteArr);
$newArr = [];
foreach ($fileArr as $key => $file){
    $newArr[$key] = $file;
    if ($currentProcessId === $file['processId']) {
        $newArr[$key]['notes'] = [ $newArr[--$key]['notes']];
        continue;
    }
    $newArr[$key]['notes'] = [];
    $currentProcessId = $file['processId'];
    while ($file['processId'] == $currentNote['processId']) {
        $newArr[$key]['notes'][$currentNote['noteId']] = $currentNote;
        $currentNote = array_pop($noteArr);
    }
}
var_dump($newArr);

附加说明:  我使用rsort来使用array_pop,它应该比array_shift

答案 3 :(得分:0)

您可以在PHP中使用一堆数组函数。

array_walk($fileArr, function(&$item) use ($noteArr) {
  $processId = $item['processId'];
  $foundNotes = array_filter($noteArr, function($note) use ($processId) {
    return $note['processId'] === $processId;
  });

  if (!empty($foundNotes)) {
    $item['notes'] = $foundNotes;
  }
});

这将使您的$fileArr变成我认为您想要的。

FWIW 我不认为嵌套循环是一种坏方法。虽然这段代码可以按照您的要求解决问题,但我认为它很难理解。