【问题标题】:Merging 2 json files where not all data matches up合并并非所有数据都匹配的 2 个 json 文件
【发布时间】:2021-09-23 05:02:14
【问题描述】:

所以我有 2 个 json 文件需要合并在一起,但情况有些独特。

所以让我们调用第一个 movies.json:

[
    {
        "title": "Title of Movie 1",
        "description": "description of Movie 1",
        "link": "CDN_url_to_movie1",
        "filters": "list, of, filters"
    }
    {
        "title": "Title of Movie 2",
        "description": "description of Movie 2",
        "link": "CDN_url_to_movie2",
        "filters": "list, of, filters"
    }
]

让我们调用第二个movies2.json

[
    {
        "title": "Title of Movie 1",
        "description": "description of Movie 1",
        "link": "CDN_url_to_movie1"
    }
        {
        "title": "Title of Movie 2",
        "description": "description of Movie 2",
        "link": "CDN_url_to_movie2",
        "filters": "list, of, filters"
    }
    {
        "title": "Title of Movie 3",
        "description": "description of Movie 3",
        "link": "CDN_url_to_movie3"
    }
]

我需要合并这两个文件以确保没有重复文件,同时考虑到一个文件或另一个文件中可能不存在过滤器。

因此我想要的 2 个示例的输出如下所示

[
    {
        "title": "Title of Movie 1",
        "description": "description of Movie 1",
        "link": "CDN_url_to_movie1",
        "filters": "list, of, filters"
    }
    {
        "title": "Title of Movie 2",
        "description": "description of Movie 2",
        "link": "CDN_url_to_movie2",
        "filters": "list, of, filters"
    }
    {
        "title": "Title of Movie 3",
        "description": "description of Movie 3",
        "link": "CDN_url_to_movie3"
    }
]

我目前拥有的如下所示

<?php
    $arr1 = file_get_contents('movies.json');
    $arr2 = json_decode($arr1, true);

    $arr3 = file_get_contents('movies2.json');
    $arr4 = json_decode($arr3, true);

    $arr5 = array_unique(array_merge($arr2, $arr4), SORT_REGULAR);

    $arr = json_encode($arr5, JSON_PRETTY_PRINT);
    file_put_contents('movies3.json', $arr);

这样的结果是:

[
    {
        "title": "Title of Movie 1",
        "description": "description of Movie 1",
        "link": "CDN_url_to_movie1",
        "filters": "list, of, filters"
    }
    {
        "title": "Title of Movie 2",
        "description": "description of Movie 2",
        "link": "CDN_url_to_movie2",
        "filters": "list, of, filters"
    }
    {
        "title": "Title of Movie 1",
        "description": "description of Movie 1",
        "link": "CDN_url_to_movie1"
    }
    {
        "title": "Title of Movie 3",
        "description": "description of Movie 3",
        "link": "CDN_url_to_movie3"
    }
]

正如我们所见,结果并不理想。尽管它删除了重复的“电影 2”,但它认为每个“电影 1”都是独一无二的……我假设是因为一个有“过滤器”键,而另一个没有。

如何合并这两个文件以获得所需的输出?

【问题讨论】:

  • 这能回答你的问题吗? Merging two json in PHP
  • @OMiShah 否,该页面上的解决方案会产生与该页面上列出的完全相同的结果。它们最终会出现重复。
  • 您能否指定条目何时重复?这不是不言而喻的。当标题相同时,它们是否相同?如果 URL 不同怎么办?同一标题的 URL 可以不同吗?还是说明?那么,我们如何确定某部电影是同一部电影,以及如何处理这些条目之间的任何差异?
  • 如果标题相同,则为重复。如果其中一个包含 filters 键,那就是要保留的那个。

标签: php arrays json


【解决方案1】:

我们在循环中合并,我们需要循环到达每个数组并将其与并行的其他数组合并 - 我稍微更改了 json 以更好地说明合并:

<?php

$movies1 = '[
    {
        "title": "Title of Movie 1",
        "description": "description of Movie 1",
        "link": "CDN_url_to_movie1",
        "filters": "list, of, filters"
    },
    {
        "title": "Title of Movie 2",
        "description": "description of Movie 2",
        "link": "CDN_url_to_movie2",
        "filters": "list, of, filters"
    },
    {
        "title": "Title of Movie 3",
        "link": "CDN_url_to_movie2",
        "filters": "list, of, filters"
    }
]';

$movies2 =  '[
    {
        "title": "Title of Movie 1",
        "description": "description of Movie 1",
        "link": "CDN_url_to_movie1"
    },
        {
        "title": "Title of Movie 2",
        "description": "description of Movie 2",
        "link": "CDN_url_to_movie2",
        "filters": "list, of, filters"
    },
    {
        "title": "Title of Movie 3",
        "description": "description of Movie 3",
        "link": "CDN_url_to_movie3"
    }
]';


$movies1A = json_decode($movies1,true);
$movies2A = json_decode($movies2,true);
echo '<pre>';
print_r($movies1A);
echo '<pre>';
print_r($movies2A);
$newM = [];
foreach ($movies1A as $key => $m1){

    foreach($movies2A as $ky => $m2){
            $newM = array_merge($m1,$m2);
            $movies2A[$key] = $newM;
    }
}
echo '<pre>';
print_r($movies2A);

将返回:

Array
(
    [0] => Array
        (
            [title] => Title of Movie 1
            [description] => description of Movie 1
            [link] => CDN_url_to_movie1
            [filters] => list, of, filters
        )

    [1] => Array
        (
            [title] => Title of Movie 2
            [description] => description of Movie 2
            [link] => CDN_url_to_movie2
            [filters] => list, of, filters
        )

    [2] => Array
        (
            [title] => Title of Movie 3
            [link] => CDN_url_to_movie2
            [filters] => list, of, filters
        )

)
Array
(
    [0] => Array
        (
            [title] => Title of Movie 1
            [description] => description of Movie 1
            [link] => CDN_url_to_movie1
        )

    [1] => Array
        (
            [title] => Title of Movie 2
            [description] => description of Movie 2
            [link] => CDN_url_to_movie2
            [filters] => list, of, filters
        )

    [2] => Array
        (
            [title] => Title of Movie 3
            [description] => description of Movie 3
            [link] => CDN_url_to_movie3
        )

)
Array
(
    [0] => Array
        (
            [title] => Title of Movie 3
            [description] => description of Movie 3
            [link] => CDN_url_to_movie3
            [filters] => list, of, filters
        )

    [1] => Array
        (
            [title] => Title of Movie 3
            [description] => description of Movie 3
            [link] => CDN_url_to_movie3
            [filters] => list, of, filters
        )

    [2] => Array
        (
            [title] => Title of Movie 3
            [link] => CDN_url_to_movie3
            [filters] => list, of, filters
            [description] => description of Movie 3
        )

)

请注意,我故意在两者中添加了标题 3,以显示它是如何合并的! :)

只需 $movies2A = json_encode($movies2A);最后,你有你想要的。

【讨论】:

    【解决方案2】:

    如果title属性对于每个数组都是唯一的,可以使用array_column函数使其成为关联数组的key,然后通过array_replace_recursive函数进行合并。

    $arr1 = json_decode($json1, true);
    $arr2 = json_decode($json2, true);
    
    $result = array_values(array_replace_recursive(
        array_column($arr1, null, 'title'),
        array_column($arr2, null, 'title')
    ));    
    

    fiddle

    【讨论】:

      【解决方案3】:

      这实际上比起初看起来要难一些。我写了一些非常明确的代码,很容易理解它的作用,这是一个正确的解决方案。

      基本上我会检测所有重复项,仅将正确的保留在另一个数组中,同时从原始数组中删除所有重复项。然后我合并原始数组并存储正确的副本。

      我不对结果进行排序。这只有在原始数组本身不包含重复项时才有效。

      <?php
      
      // it is obvious what this starts with, so I left that out
      $movies1 = json_decode($moviesJson1);
      $movies2 = json_decode($moviesJson2);
      
      // first we find the duplicated movies, and choose the one with filters
      $duplicates = [];
      $removeKeys1 = [];
      $removeKeys2 = [];
      foreach ($movies1 as $key1 => $movie1) {
          foreach ($movies2 as $key2 => $movie2) {
              if ($movie1->title == $movie2->title) {
                  $duplicates[] = property_exists($movie1, "filters") ? $movie1 : $movie2;
                  $removeKeys1[] = $key1;
                  $removeKeys2[] = $key2;
              }
          }    
      }
      
      // then we remove all duplicated movies from the original arrays
      foreach ($removeKeys1 as $key) {
          unset($movies1[$key]);
      }
      foreach ($removeKeys2 as $key) {
          unset($movies2[$key]);
      }
      
      // finally we merge everything that's left
      $movies = array_merge($movies1, $movies2, $duplicates);
      $moviesJson = json_encode($movies, JSON_PRETTY_PRINT);
      
      echo $moviesJson;
      

      这会返回:

      [
          {
              "title": "Title of Movie 3",
              "description": "description of Movie 3",
              "link": "CDN_url_to_movie3"
          },
          {
              "title": "Title of Movie 1",
              "description": "description of Movie 1",
              "link": "CDN_url_to_movie1",
              "filters": "list, of, filters"
          },
          {
              "title": "Title of Movie 2",
              "description": "description of Movie 2",
              "link": "CDN_url_to_movie2",
              "filters": "list, of, filters"
          }
      ]
      

      这里是the working demo code

      如前所述,编写此代码并不是为了提供最聪明的解决方案,而只是为了提供真正有效的代码。但是,因为可以,所以我添加了一个没有键数组的版本:

      $movies1 = json_decode($moviesJson1);
      $movies2 = json_decode($moviesJson2);
      
      // first we find the duplicated movies, and choose the one with filters
      $duplicates = [];
      foreach ($movies1 as $key1 => $movie1) {
          foreach ($movies2 as $key2 => $movie2) {
              if ($movie1->title == $movie2->title) {
                  $duplicates[] = property_exists($movie1, "filters") ? $movie1 : $movie2;
              }
          }    
      }
      
      // then we remove all duplicated movies from the original arrays by title
      $duploTitles = array_column($duplicates, "title");
      foreach (["movies1", "movies2"] as $arrayName) {
          foreach (array_column(${$arrayName}, "title") as $key => $title) {
              if (in_array($title, $duploTitles)) {
                  unset(${$arrayName}[$key]);
              }    
          }
      }
      
      // finally we merge everything that's left
      $movies = array_merge($movies1, $movies2, $duplicates);
      $moviesJson = json_encode($movies, JSON_PRETTY_PRINT);
      

      这里是the working demo code

      这完全一样。你可以称这段代码更聪明一点,但老实说,它可能会稍微慢一些,而且肯定更难理解。我会使用第一个解决方案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-26
        相关资源
        最近更新 更多