所以我有两个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"
}
]
我需要以一种没有重复的方式合并这两个文件,同时考虑到过滤器可能不存在于一个文件或另一个文件中。
因此,我想从这两个例子中得到的输出看起来像[
{
"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"。它考虑了每一部"电影"独特的…我猜是因为有"过滤器"键,另一个不。
我如何合并这两个文件,这样我将得到想要的输出?
我们在循环中合并,我们需要循环到达每个数组并将其与并行的其他数组合并-我已经改变了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);在最后,你得到了你想要的。
如果每个数组的title
属性都是唯一的,则可以使用array_column
函数将其作为关联数组的键,然后通过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')
));
小提琴
这实际上比乍看起来要难一些。我写了一些非常明确的代码,很容易理解它的作用,这是一个正确的解决方案。
基本上我检测所有重复项,只在另一个数组中保留正确的项,同时从原始数组中删除所有重复项。然后合并原始数组并存储正确的重复项。
我不排序结果。这只会在原始数组本身不包含重复项的情况下起作用。
<?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"
}
]
下面是工作演示代码
如前所述,这段代码并不是为了呈现最聪明的解决方案而编写的,而只是实际工作的代码。但是,因为我可以,所以我添加了一个没有键数组的版本:$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);
下面是工作演示代码
的作用完全相同。您可以将此代码调用得更聪明一些,但是,说实话,它可能会稍微慢一些,而且肯定更难以理解。我将使用第一种解决方案。