如何在不产生冗余的情况下高效查询嵌套的JSON关系(reacts_with、affected_by)?

前端开发 2026-07-09

我正在处理一个结构化的JSON数据集,其中每种成分包含关系元数据,例如:

  • reacts_with
  • affected_by
  • compatible_with

简化后的结构大致如下:

{
  "category": "surfactants",
  "ingredients": [
    {
      "name": "sodium stearate",
      "reacts_with": ["calcium", "magnesium"],
      "affected_by": ["hard_water"],
      "compatible_with": ["nonionic_surfactants"]
    }
  ]
}

完整数据集(供参考): https://cleanformulation.com/data/ingredients-dataset.json

我想要找出:

  1. 受 "hard_water" 影响的所有成分
  2. 与 "calcium" 发生反应的所有成分

我当前使用的一个简单的PHP循环是这样的:

<?php

$data = json_decode(file_get_contents('ingredients-dataset.json'), true);
$result = [];

foreach ($data as $category) {
    foreach ($category['ingredients'] as $ingredient) {
        if (in_array('hard_water', $ingredient['affected_by'])) {
            $result[] = $ingredient['name'];
        }
    }
}

print_r($result);
?>

这对于小数据量来说工作正常,但随着数据集的增大,效率会下降,因为我每次都得遍历所有类别和成分
在查询多个关系时,感觉有些冗余

有没有办法在PHP中查询这些关系,而不必每次都进行完整的遍历?

解决方案

根据链接中的json结构,我们可以像注释所建议的那样,使用关联数组获得线性结果。我假设你会一次性加载JSON,然后对数据执行多次查询:

<?php
$data = json_decode( file_get_contents( 'ingredients-dataset.json' ), true );

$interactions = [
    "affected_by" => [],
    "binds" => [],
];

// Walking the JSON structure
foreach ( $data['categories'] as $category ) {
    foreach( $category['pages'] as $page ) {
        // Preventing warnings
        if ( !array_key_exists( 'interactions', $page ) ) {
            continue;
        }
        // Note the reference &
        foreach( $interactions as $action => &$action_array ) {
            if ( !array_key_exists( $action, $page["interactions"] ) ) {
                continue;
            }
            foreach( $page['interactions'][$action] as $interactant ) {
                // Create new empty array, if it doesn't exist already
                if ( !isset( $action_array[$interactant] ) ) {
                    $action_array[$interactant] = [];
                }
                // Add to said array
                $action_array[$interactant][] = $page["id"];
            }
        }
    }
}
// Print the results
echo "affected_by hard-water: "
    .implode( ", ", $interactions["affected_by"]["hard-water"] )
    ."<br>";

echo "binds to calcium-ions: "
    .implode( ", ", $interactions["binds"]["calcium-ions"] )
    ."<br>";

结果:

affected_by hard-water: coconut-oil, aqua
binds to calcium-ions: etidronic-acid, tetrasodium-edta
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章