PAYATHON 2026

PHP 如何遍历 JSON 中的 features 并获取当前和下一项的 city?

数据小陈

可以在 foreach 中取得当前数组索引,再通过 $features[$i + 1] 读取下一项。索引访问不会改变外层循环的遍历进度,因此会依次配对第 1、2 项,第 2、3 项,第 3、4 项,以此类推。

为什么可以通过索引访问下一项

按题目中的调用方式,json_decode($file) 会将 JSON 对象解析为对象,将 JSON 数组解析为 PHP 数组。因此:

  • $path 是对象,使用 ->features 访问属性。
  • $path->features 是数组,使用 [0]、[1] 等索引访问元素。
  • 每个 feature 及其 properties 是对象,使用 ->properties->city 访问 city。

如果只需要第二个 feature 的 city,可以直接读取:

$city = $path->features[1]->properties->city;

题目中该值为 YYY。数组索引从 0 开始,所以第二项的索引是 1。

保留 foreach,逐次读取相邻两项

下面的代码会读取文件、解析 JSON 并检查 features 的类型。循环部分假设每个 feature 都具有题目所示的 properties.city 结构。

<?php

$file = file_get_contents('file.json');
if ($file === false) {
    exit("无法读取 file.json\n");
}

$path = json_decode($file);
if (JSON_ERROR_NONE !== json_last_error()) {
    exit(json_last_error_msg() . "\n");
}

if (!isset($path->features) || !is_array($path->features)) {
    exit("JSON 中缺少 features 数组\n");
}

$features = $path->features;

foreach ($features as $i => $routes) {
    // 最后一项没有下一项,不再组成配对。
    if (!isset($features[$i + 1])) {
        break;
    }

    $start = $routes->properties->city;
    $finish = $features[$i + 1]->properties->city;

    printf("%s -> %s\n", $start, $finish);
}

对于题目中的两项数据,输出为:

XXX -> YYY

$routes 是当前项,$features[$i + 1] 是下一项。读取下一项后,下一次 foreach 循环仍会从原本的下一项开始。

最后一项如何处理

最后一项没有后继元素,因此不能再组成相邻配对。包含 n 个有效 feature 的数组会得到 n - 1 组配对;空数组或只有一项的数组不会产生配对。

示例中的 isset() 检查适用于题目给出的 feature 对象数组。如果数组可能包含 null,或者 feature 缺少 properties.city,需要根据实际数据规则决定报错还是跳过。跳过异常项可能改变预期的配对关系。

配对使用的是 features 的数组顺序。properties.step 不参与索引计算,也不会自动决定遍历顺序。

原代码还需要修正的语法

原片段在 JSON 错误检查之后多了一个 };给 $start 赋值时,末尾也多了一个 )。正确写法是:

$start = $routes->properties->city;

PHP 变量名需要以 $ 开头,所以应使用 $finish。完成下一项的边界检查后,将赋值部分改为下面两行,即可取得当前项和下一项的 city:

$start = $routes->properties->city;
$finish = $features[$i + 1]->properties->city;

备注:内容仅供参考。