<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>VR train search</title>
<!--
Data provided by https://www.digitraffic.fi/, used under the following license:
Creative Commons Attribution 4.0 International (CC BY 4.0)
Search for train connections through the VR API
https://www.digitraffic.fi/rautatieliikenne/#reittiperusteinen-haku
-->
</head>
<body>
<h3>Train search</h3>
<form>
<p>Ignore the search fields, I have hard-coded the stations in this example to make the code shorter. Just click Search trains.</p>
<label>From:</label>
<input type = "text" id = "departure_station">
<label>To:</label>
<input type = "text" id = "arrival_station">
<label>Date (yyyy-mm-dd):</label>
<input type = "text" id = "departure_date">
<input type = "button" value = "Search trains" onclick = "searchTrains()">
</form>
<div id = "onscreen_text"></div>
<script type = "text/javascript">
function searchTrains() {
var departure_station = "HKI";
var arrival_station = "TPE";
var departure_date = "2019-02-12";
var xmlhttp = new XMLHttpRequest();
var json;
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
json = xmlhttp.responseText;
listResults(json);
}
if (xmlhttp.readyState == 4 && xmlhttp.status == 404) {
document.getElementById("onscreen_text").innerHTML = "<p>No search results found in the VR API.</p>";
}
}
// Get the data from the API
xmlhttp.open(
"GET", "https://rata.digitraffic.fi/api/v1/live-trains/station/" + departure_station + "/" + arrival_station + "?" + "departure_date = " + departure_date + "&limit=10", true);
xmlhttp.send();
}
function listResults(json) {
var results = JSON.parse(json);
console.info(results); // testing
var text = ""; // testing
// filter results for only passenger trains
var passengerTrains = [];
function getPassengerTrains() {
for (var i = 0; i < results.length; i++) {
if (results[i].trainCategory == "Long-distance" || results[i].trainCategory == "Commuter") {
passengerTrains.push(results[i]);
text = text + results[i].trainNumber + "<br>"; // testing
}
}
}
getPassengerTrains();
console.info(passengerTrains); // testing
// Get the desired properties from the filtered trains
// https://stackoverflow.com/questions/37750309/find-object-by-property-in-an-array-of-javascript-objects-inside-another-array
var station = passengerTrains.map(item => item.timeTableRows.stationShortCode);
console.info(station); // but this returns an array full of undefined
// Loop through array of train objects
for (var i = 0; i < passengerTrains.length; i++) {
console.info(passengerTrains[i]); // this seems to give the right result
// Loop through each train object to get timeTableRows subarray
for (var train in passengerTrains[i]) {
// make a new array named timetable
var timetable = passengerTrains[i].timeTableRows;
console.info(timetable);
// but this prints the same array 13 times = as many times as there are properties in the train object
/* Commented out because it freezes my browser
// Loop through each object in the timetable subarray to get the desired properties
for (var j=0; j < timetable.length; j++) {
console.info(timetable[j]);
for (var row in timetable[j]) {
text = text + "<p>From/to: " + timetable[j].stationShortCode;
text = text + "<br>Time: " + timetable[j].scheduledTime;
text = text + "<br>Train stopping: " + timetable[j].trainStopping;
text = text + "<br>Departure/arrival: " + timetable[j].type + "</p>";
}
} */
}
document.getElementById("onscreen_text").innerHTML = text;
}
}
</script>
</body>
</html>Я новичок в программировании, и это мой первый вопрос здесь. Я застрял, пытаясь понять, как добраться до нижнего уровня многоуровневого вложенного массива/объекта в JavaScript.
Я работаю с проанализированным JSON-файлом расписания поездов типа, возвращаемого этим общедоступным API: https://rata.digitraffic.fi/api/v1/live-trains/station/HKI/TPE?departure_date=2019-02-12
Проанализированный результат представляет собой массив объектов поезда с подмассивом с именем timeTableRows, полным объектов со свойствами, такими как stationShortCode: «HKI», запланированное время: «2019-02-12T05:04:00.000Z» и т. д. Я хочу добраться до этих свойства нижнего уровня. Скрин из консоли для ясности
Я попробовал ответ, данный здесь: Найти объект по свойству в массиве объектов JavaScript внутри другого массива
Но я не могу понять, как заставить его работать для меня, так как мне не нужно находить определенный индекс, а только свойство с определенным именем, и мои попытки возвращают только «неопределенное». Я совсем не знаком с ES5, поэтому был бы признателен за несколько примеров, подходящих для начинающих.
Я закомментировал остальные циклы for, так как они создавали повторяющееся чудовище, которое зависало в моем браузере. Есть ли способ добраться до нижнего уровня такой структуры без многократного повторения всего?
js snippet removedПожалуйста, редактировать ваш вопрос, чтобы включить пример данных, которые вы ищете. Не все могут получить доступ к сайту, если они находятся за брандмауэрами и т. д. Вы можете включить его в свой фрагмент, чтобы нажатие «Выполнить фрагмент кода» приводило к чему-то другому, кроме ошибки :).
Спасибо, я преобразовал пример в полноценный HTML-файл, чтобы он запускался и выдавал данные в консоли. По какой-то причине здесь он работает очень медленно, но нет проблем, если я запускаю его прямо из Блокнота в Firefox. Скриншот в моем посте также показывает структуру массива с данными, которые я ищу на нижнем уровне (stationShortCode и т.д.).



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете использовать Ramda для этого, https://ramdajs.com/docs/#путь. Это даст вам значение желаемого свойства, введя путь, чтобы вы могли использовать его следующим образом:
R.map(train => {
train_id:train.trainNumber,
timeTableRows:R.path(["path","to","property"],train)
}, trains)
function fetchNestedObject(prop, obj) {
let keys = prop.split('.');
keys[0] = obj[keys[0]];
return keys.reduce((a, b) => a && a[b]);
}
Использование:
fetchNestedObject('v.a.d.0', {v: {a: {d: [1]}}})
Спасибо за ответы выше, я отмечу их для дальнейшего использования, хотя они слишком продвинуты для моего текущего уровня знаний JS. Прямо сейчас мне удалось создать серию вложенных циклов for, которые, кажется, делают то, что я хочу, но я буду рад получить дальнейшие комментарии или улучшения по этому решению.
Подводя итог, проблема заключалась в извлечении данных на четыре уровня ниже свойств объекта внутри массива, который находится внутри другого объекта внутри массива верхнего уровня (анализируемый ответ JSON).
// passengerTrains is the top-level array
for (var i = 0; i < passengerTrains.length; i++) {
var train = passengerTrains[i]; // each train is an object
//console.info(train);
var trainNumber = train.trainNumber;
//console.info(trainNumber);
// Loop through array of timeTableRows inside each train object
for (var j = 0; j < train.timeTableRows.length; j++) {
var row = train.timeTableRows[j]; // each row is an object
// console.info(row);
// Print out only the data that we want
// The variables dep and arr are defined elsewhere in the code
if (row.stationShortCode == dep && row.type == "DEPARTURE") {
text = text + "Train " + trainNumber + ": Departure from " + departure_station + " at " + row.scheduledTime + "<br>";
console.info("Train " + trainNumber + ": Departure from " + departure_station + " at " + row.scheduledTime);
}
if (row.stationShortCode == arr && row.type == "ARRIVAL") {
text = text + "Train " + trainNumber + ": Arrival at " + arrival_station + " at " + row.scheduledTime + "<br><br>";
console.info("Train " + trainNumber + ": Arrival at " + arrival_station + " at " + row.scheduledTime);
}
}
document.getElementById("onscreen_text").innerHTML = text;
}
вы должны использовать рекурсивный метод, который будет проходить через весь объект, пока он не найдет дополнительных детей