如何从JavaScript的另一个对象数组中的对象数组获取底层属性

时间:2019-02-11 15:08:11

标签: javascript arrays

<!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.log(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.log(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.log(station); // but this returns an array full of undefined
		
		// Loop through array of train objects
		for (var i = 0; i < passengerTrains.length; i++) {
			console.log(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.log(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.log(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中多层嵌套数组/对象事物的最底层。

我正在使用的是此公共API返回的类型的火车时刻表的已解析JSON文件: https://rata.digitraffic.fi/api/v1/live-trains/station/HKI/TPE?departure_date=2019-02-12

解析的结果是一个训练对象数组,该数组具有名为timeTableRows的子数组,该数组充满了具有诸如stationShortCode:“ HKI”,ScheduledTime:“ 2019-02-12T05:04:00.000Z”等属性的对象。进入这些底层属性。 Screenshot from console for clarity

我尝试了这里给出的答案: Find object by property in an array of JavaScript objects inside another array

但是我不知道如何使它对我有用,因为我不需要找到某个索引,而只需找到具有特定名称的属性,并且我的尝试只会返回“ undefined”。我对ES5一点都不熟悉,所以我会喜欢一些对初学者友好的示例。

我注释了其余的for循环,因为它们创建了一个反复出现的怪兽,使我的浏览器不知所措。有什么方法可以使这种结构的底层达到最低水平而又不会遍历所有事物?

js snippet removed

3 个答案:

答案 0 :(得分:1)

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]}}})

答案 1 :(得分:0)

您可以为此使用Ramda,https://ramdajs.com/docs/#path。 通过输入路径,这将为您提供所需属性的值,因此您可以按以下方式使用它:

R.map(train => {
    train_id:train.trainNumber,
    timeTableRows:R.path(["path","to","property"],train)
}, trains)

答案 2 :(得分:0)

感谢您提供上述答案,尽管对于我目前的JS知识水平而言,它们还是太高级了,但我会记下它们以备后用。现在,我设法创建了一系列嵌套的循环,这些循环似乎可以完成我想要的工作,但是我很乐意收到对此解决方案的进一步评论或改进。

总而言之,问题在于从数组内部的对象的属性向下四级提取数据,该对象位于顶级数组内部的另一个对象(已解析的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.log(train);
            var trainNumber = train.trainNumber;
            //console.log(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.log(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.log("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.log("Train " + trainNumber + ": Arrival at " + arrival_station + " at " + row.scheduledTime);
                }
            }
        document.getElementById("onscreen_text").innerHTML = text;
        }