JavaScript
Node.js
AdventCalendar
駅すぱあと

配列のソートを利用して簡単に探索結果の並び変えをやってみる

More than 1 year has passed since last update.

ヴァル研究所 Advent Calendar 2016 の9日目はJavaScriptに関するお話です。


JavaScriptは簡単だけど、複雑・・・

JavaScriptって簡単に実装できる代わり、バージョンがいっぱいあったりブラウザ依存で動いたり動かなかったり、いろいろなライブラリなんかもあって良く分からなくなることありませんか?

今でも「このブラウザでは動く」、「特定のブラウザで動かない」なんてことを耳にします。

何となくやっちゃうプログラミングと駅すぱあとにも応用できるソートについて紹介します。


配列をソートしてみる

たとえば、こんな感じの配列があったとします。

var list = [5, 1, 6, 2, 9, 3, 7, 4, 8];

これをソートする場合、こんな感じで実装していませんか?

for (var i = 0; i < list.length; i++) {

for (var j = i + 1; j < list.length; j++) {
if (list[i] > list[j]) {
var temporary = list[i];
list[i] = list[j];
list[j] = temporary;
}
}
}

動かないわけじゃないし、説明も簡単なので、プログラミングのお勉強で書いたことあるって人も多いのではないでしょうか?


Array.prototype.sort()を使ってみる

Arrayのsortを使うとすごく簡単にソートが実装できます。

list.sort(function (a, b) {

if (a > b) return 1;
if (a < b) return -1;
return 0;
});

これで「1,2,3,4,5,6,7,8,9」が取得できます。

しかも、結構古めのブラウザでも対応していて、今なら依存などはほぼ考えなくて大丈夫ですね。

(というより、現時点でサポートされているブラウザのほとんどが対応してます)

(sortの詳細は https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/sort を参照)


本題!探索結果をソートしてみる

経路探索については4日目を見てね。

ヴァル研究所 Advent Calendar 2016、4日目

さて、探索結果のソートです。

用意した探索結果を早速料理していきましょう。

{"ResultSet":{"apiVersion":"1.27.0.0","engineVersion":"201612_02a","Course":[{"searchType":"plain","dataType":"plain","SerializeData":"VkV4QaEByALDAqYBM6KyA6YBM6KyBJHCAUMAAAACpgEzorIDyAEBAgEDAQQBBwEIAQoCD0JAAAWSwQKlWI_BAqVY1QaRwwEEAgEDwQGk3QeRxQGmATOitgOBBIEFAAgACJHEBAEFAQekbQgBCZHBAwEPkcUBkgABApHDAQACAAMAA5HDAQACAAMABJEABZEA--T3221233232319:F3321122120:A23121141:--a7acdaacc1ab2bd0f3f92adf3e4abaa62e257cc3--0--0--0--144","Price":[{"kind":"FareSummary","Oneway":"160","Round":"320"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Fare","index":"1","selected":"true","Type":"Fare","Oneway":"160","Round":"320"},{"kind":"Teiki1Summary","Oneway":"4850"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Teiki1","index":"1","selected":"true","Type":"Teiki1","Oneway":"4850"},{"kind":"Teiki3Summary","Oneway":"13820"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Teiki3","index":"1","selected":"true","Type":"Teiki3","Oneway":"13820"},{"kind":"Teiki6Summary","Oneway":"23260"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Teiki6","index":"1","selected":"true","Type":"Teiki6","Oneway":"23260"}],"Route":{"timeOther":"6","timeOnBoard":"6","exhaustCO2":"127","exhaustCO2atPassengerCar":"974","distance":"58","timeWalk":"0","transferCount":"0","Line":{"direction":"Up","stopStationCount":"1","teiki3Index":"1","teiki6Index":"1","timeOnBoard":"6","exhaustCO2":"127","fareIndex":"1","exhaustCO2atPassengerCar":"974","distance":"58","teiki1Index":"1","Name":"JR中央線快速","Type":"train","ArrivalState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"TypicalName":"JR中央線快速","TimeReliability":"none","DepartureState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"Color":"250060002"},"Point":[{"Station":{"code":"22671","Name":"高円寺","Type":"train","Yomi":"こうえんじ"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.39.10.89","lati":"35.42.7.59","longi_d":"139.653027","gcs":"tokyo","lati_d":"35.70211"}},{"Station":{"code":"22741","Name":"新宿","Type":"train","Yomi":"しんじゅく"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.42.11.0","lati":"35.41.15.0","longi_d":"139.703056","gcs":"tokyo","lati_d":"35.6875"}}]}},{"searchType":"plain","dataType":"plain","SerializeData":"VkV4QaEByQLDAqYBM6KyA6YBM6KyBJHCAUMAAAACpgEzorIDyAEBAgEDAQQBBwEIAQoCD0JAAAWUwQKlWI_BAqVZQcECpVkGwQKlWNUGk8MBBAIBA8EBpQGFwwEEAgEDwQGlBIjDAQQCAQPBAaS4B5PFAaYBM6K2A4EEgQUgCADGAaYBM6K2AgEDgQSBBRAIAMYBpgEzorYCAgOBBIEFAAgACJPEBAEFAQekbggBxgIBBAIFAQYBB6UBSwgCxQICBAMFAQelAs0IAwmSwgIBAwHDAQICAgMBCpOgwwEBAgEDAcIBAgICD5HFAZQAAQIDApPDAQACAAMAwwEBAgEDAcMBAgICAwIDk8MBAAIAAwDDAQECAQMBwwECAgIDAgSSAAEFkQE*--T3221233232319:F3321122120:A23121141:--e5b02b81e77e4c7c56baeb0a262e3e3950553d8d--0--0--0--293","Price":[{"kind":"FareSummary","Oneway":"430","Round":"860"},{"fareRevisionStatus":"none","toLineIndex":"2","fromLineIndex":"1","kind":"Fare","index":"1","selected":"true","Type":"Fare","Oneway":"290","Round":"580"},{"fareRevisionStatus":"none","toLineIndex":"3","fromLineIndex":"3","kind":"Fare","index":"2","selected":"true","Type":"Fare","Oneway":"140","Round":"280"},{"kind":"Teiki1Summary","Oneway":"14400"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Teiki1","index":"1","selected":"true","Type":"Teiki1","Oneway":"3880"},{"fareRevisionStatus":"none","toLineIndex":"2","fromLineIndex":"2","kind":"Teiki1","index":"2","selected":"true","Type":"Teiki1","Oneway":"6640"},{"fareRevisionStatus":"none","toLineIndex":"3","fromLineIndex":"3","kind":"Teiki1","index":"3","selected":"true","Type":"Teiki1","Oneway":"3880"},{"kind":"Teiki3Summary","Oneway":"41050"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Teiki3","index":"1","selected":"true","Type":"Teiki3","Oneway":"11060"},{"fareRevisionStatus":"none","toLineIndex":"2","fromLineIndex":"2","kind":"Teiki3","index":"2","selected":"true","Type":"Teiki3","Oneway":"18930"},{"fareRevisionStatus":"none","toLineIndex":"3","fromLineIndex":"3","kind":"Teiki3","index":"3","selected":"true","Type":"Teiki3","Oneway":"11060"},{"kind":"Teiki6Summary","Oneway":"73100"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Teiki6","index":"1","selected":"true","Type":"Teiki6","Oneway":"18620"},{"fareRevisionStatus":"none","toLineIndex":"2","fromLineIndex":"2","kind":"Teiki6","index":"2","selected":"true","Type":"Teiki6","Oneway":"35860"},{"fareRevisionStatus":"none","toLineIndex":"3","fromLineIndex":"3","kind":"Teiki6","index":"3","selected":"true","Type":"Teiki6","Oneway":"18620"}],"Route":{"timeOther":"9","timeOnBoard":"12","exhaustCO2":"176","exhaustCO2atPassengerCar":"1344","distance":"80","timeWalk":"0","transferCount":"1","Line":[{"direction":"Up","stopStationCount":"0","teiki3Index":"1","teiki6Index":"1","timeOnBoard":"2","exhaustCO2":"30","fareIndex":"1","exhaustCO2atPassengerCar":"235","distance":"14","teiki1Index":"1","Name":"JR総武線","Type":"train","ArrivalState":{"Type":"extension","Datetime":{"text":"2016-12-06","operation":"today"}},"TypicalName":"JR総武線","TimeReliability":"none","DepartureState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"Color":"255222000"},{"direction":"Down","stopStationCount":"1","teiki3Index":"2","teiki6Index":"2","timeOnBoard":"6","exhaustCO2":"85","fareIndex":"1","exhaustCO2atPassengerCar":"655","distance":"39","teiki1Index":"2","Name":"東京メトロ東西線","Type":"train","ArrivalState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"TypicalName":"東京メトロ東西線","TimeReliability":"none","DepartureState":{"Type":"extension","Datetime":{"text":"2016-12-06","operation":"today"}},"Color":"012118255"},{"direction":"Down","stopStationCount":"1","teiki3Index":"3","teiki6Index":"3","timeOnBoard":"4","exhaustCO2":"59","fareIndex":"2","exhaustCO2atPassengerCar":"453","distance":"27","teiki1Index":"3","Name":"JR山手線内回り","Type":"train","ArrivalState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"TypicalName":"JR山手線内回り","TimeReliability":"none","DepartureState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"Color":"045232013"}],"Point":[{"Station":{"code":"22671","Name":"高円寺","Type":"train","Yomi":"こうえんじ"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.39.10.89","lati":"35.42.7.59","longi_d":"139.653027","gcs":"tokyo","lati_d":"35.70211"}},{"Station":{"code":"22849","Name":"中野(東京都)","Type":"train","Yomi":"なかの"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.40.9.0","lati":"35.42.9.29","longi_d":"139.669167","gcs":"tokyo","lati_d":"35.702582"}},{"Station":{"code":"22790","Name":"高田馬場","Type":"train","Yomi":"たかだのばば"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.42.27.0","lati":"35.42.36.39","longi_d":"139.7075","gcs":"tokyo","lati_d":"35.710111"}},{"Station":{"code":"22741","Name":"新宿","Type":"train","Yomi":"しんじゅく"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.42.11.0","lati":"35.41.15.0","longi_d":"139.703056","gcs":"tokyo","lati_d":"35.6875"}}]}},{"searchType":"plain","dataType":"plain","SerializeData":"VkV4QaEByQLDAqYBM6KyA6YBM6KyBJHCAUMAAAACpgEzorIDyAEBAgEDAQQBBwEIAQoCD0JAAAWTwQKlWI_BAqVZmMECpVjVBpLDAQQCAQPBAaUBhcMBBAIBA8EBpQflB5LFAaYBM6K2A4EEgQUACADGAaYBM6K2AgEDgQSBBQAIAAiSxAQBBQEHpG4IAcUCAQQCBQEHpQLRCAIJksEDAcMBAQIBAwEKkqDDAQECAQMBD5HFAZMAAQICksMBAAIAAwDDAQECAQMBA5LDAQACAAMAwwEBAgEDAQSSAAEFkQE*--T3221233232319:F3321122120:A23121141:--07535bbdf639e8238e41c45659537e0269a46c6a--0--0--0--224","Price":[{"kind":"FareSummary","Oneway":"340","Round":"680"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Fare","index":"1","selected":"true","Type":"Fare","Oneway":"160","Round":"320"},{"fareRevisionStatus":"none","toLineIndex":"2","fromLineIndex":"2","kind":"Fare","index":"2","selected":"true","Type":"Fare","Oneway":"180","Round":"360"},{"kind":"Teiki1Summary","Oneway":"12290"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Teiki1","index":"1","selected":"true","Type":"Teiki1","Oneway":"4850"},{"fareRevisionStatus":"none","toLineIndex":"2","fromLineIndex":"2","kind":"Teiki1","index":"2","selected":"true","Type":"Teiki1","Oneway":"7440"},{"kind":"Teiki3Summary","Oneway":"35030"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Teiki3","index":"1","selected":"true","Type":"Teiki3","Oneway":"13820"},{"fareRevisionStatus":"none","toLineIndex":"2","fromLineIndex":"2","kind":"Teiki3","index":"2","selected":"true","Type":"Teiki3","Oneway":"21210"},{"kind":"Teiki6Summary","Oneway":"63440"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Teiki6","index":"1","selected":"true","Type":"Teiki6","Oneway":"23260"},{"fareRevisionStatus":"none","toLineIndex":"2","fromLineIndex":"2","kind":"Teiki6","index":"2","selected":"true","Type":"Teiki6","Oneway":"40180"}],"Route":{"timeOther":"14","timeOnBoard":"12","exhaustCO2":"156","exhaustCO2atPassengerCar":"1192","distance":"71","timeWalk":"0","transferCount":"1","Line":[{"direction":"Up","stopStationCount":"1","teiki3Index":"1","teiki6Index":"1","timeOnBoard":"4","exhaustCO2":"72","fareIndex":"1","exhaustCO2atPassengerCar":"554","distance":"33","teiki1Index":"1","Name":"JR総武線","Type":"train","ArrivalState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"TypicalName":"JR総武線","TimeReliability":"none","DepartureState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"Color":"255222000"},{"direction":"Up","stopStationCount":"3","teiki3Index":"2","teiki6Index":"2","timeOnBoard":"8","exhaustCO2":"83","fareIndex":"2","exhaustCO2atPassengerCar":"638","distance":"38","teiki1Index":"2","Name":"都営大江戸線","Type":"train","ArrivalState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"TypicalName":"都営大江戸線","TimeReliability":"none","DepartureState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"Color":"255107107"}],"Point":[{"Station":{"code":"22671","Name":"高円寺","Type":"train","Yomi":"こうえんじ"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.39.10.89","lati":"35.42.7.59","longi_d":"139.653027","gcs":"tokyo","lati_d":"35.70211"}},{"Station":{"code":"22936","Name":"東中野","Type":"train","Yomi":"ひがしなかの"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.41.12.50","lati":"35.42.11.0","longi_d":"139.686806","gcs":"tokyo","lati_d":"35.703056"}},{"Station":{"code":"22741","Name":"新宿","Type":"train","Yomi":"しんじゅく"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.42.11.0","lati":"35.41.15.0","longi_d":"139.703056","gcs":"tokyo","lati_d":"35.6875"}}]}},{"searchType":"plain","dataType":"plain","SerializeData":"VkV4QaEByQLDAqYBM6KyA6YBM6KyBJHCAUMAAAACpgEzorIDyAEBAgEDAQQBBwEIAQoCD0JAAAWVwQKlWI_BAqVZmMECpVk8wQKlWQbBAqVY1QaUwwEEAgEDwQGlAYXDAQQCAQPBAaUH5MMBBAIBA8EBpQNrwwEEAgEDwQGkuAeUxQGmATOitgOBBIEFAAgAxgGmATOitgIBA4EEgQUACADGAaYBM6K2AgIDgQSBBQAIAMYBpgEzorYCAwOBBIEFAAgACJTEBAEFAQekbggBxgIBBAIFAQYBB6UC0QgCxQICBAMFAQelASAIA8UCAwQEBQEHpQLNCAQJk8EDAcMBAQICAwHDAQMCAwMBCpOgwwEBAgEDAcMBAgIDAwEPkcUBlQABAgMEApTDAQACAAMAwwEBAgEDAcMBAgICAwLDAQMCAwMDA5TDAQACAAMAwwEBAgEDAcMBAgICAwLDAQMCAwMDBJMAAQIFkgEC--T3221233232319:F3321122120:A23121141:--3bba9b2beec52b0f1f63740af2e55329bf38eb54--0--0--0--363","Price":[{"kind":"FareSummary","Oneway":"610","Round":"1220"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Fare","index":"1","selected":"true","Type":"Fare","Oneway":"160","Round":"320"},{"fareRevisionStatus":"none","toLineIndex":"3","fromLineIndex":"2","kind":"Fare","index":"2","selected":"true","Type":"Fare","Oneway":"310","Round":"620"},{"fareRevisionStatus":"none","toLineIndex":"4","fromLineIndex":"4","kind":"Fare","index":"3","selected":"true","Type":"Fare","Oneway":"140","Round":"280"},{"kind":"Teiki1Summary","Oneway":"20500"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Teiki1","index":"1","selected":"true","Type":"Teiki1","Oneway":"4850"},{"fareRevisionStatus":"none","toLineIndex":"2","fromLineIndex":"2","kind":"Teiki1","index":"2","selected":"true","Type":"Teiki1","Oneway":"6340"},{"fareRevisionStatus":"none","toLineIndex":"4","fromLineIndex":"3","kind":"Teiki1","index":"3","selected":"true","Type":"Teiki1","Oneway":"9310"},{"kind":"Teiki3Summary","Oneway":"58430"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Teiki3","index":"1","selected":"true","Type":"Teiki3","Oneway":"13820"},{"fareRevisionStatus":"none","toLineIndex":"2","fromLineIndex":"2","kind":"Teiki3","index":"2","selected":"true","Type":"Teiki3","Oneway":"18070"},{"fareRevisionStatus":"none","toLineIndex":"4","fromLineIndex":"3","kind":"Teiki3","index":"3","selected":"true","Type":"Teiki3","Oneway":"26540"},{"kind":"Teiki6Summary","Oneway":"105450"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Teiki6","index":"1","selected":"true","Type":"Teiki6","Oneway":"23260"},{"fareRevisionStatus":"none","toLineIndex":"2","fromLineIndex":"2","kind":"Teiki6","index":"2","selected":"true","Type":"Teiki6","Oneway":"34240"},{"fareRevisionStatus":"none","toLineIndex":"4","fromLineIndex":"3","kind":"Teiki6","index":"3","selected":"true","Type":"Teiki6","Oneway":"47950"}],"Route":{"timeOther":"19","timeOnBoard":"13","exhaustCO2":"191","exhaustCO2atPassengerCar":"1461","distance":"87","timeWalk":"0","transferCount":"3","Line":[{"direction":"Up","stopStationCount":"1","teiki3Index":"1","teiki6Index":"1","timeOnBoard":"4","exhaustCO2":"72","fareIndex":"1","exhaustCO2atPassengerCar":"554","distance":"33","teiki1Index":"1","Name":"JR総武線","Type":"train","ArrivalState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"TypicalName":"JR総武線","TimeReliability":"none","DepartureState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"Color":"255222000"},{"direction":"Down","stopStationCount":"0","teiki3Index":"2","teiki6Index":"2","timeOnBoard":"2","exhaustCO2":"17","fareIndex":"2","exhaustCO2atPassengerCar":"134","distance":"8","teiki1Index":"2","Name":"都営大江戸線","Type":"train","ArrivalState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"TypicalName":"都営大江戸線","TimeReliability":"none","DepartureState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"Color":"255107107"},{"direction":"Up","stopStationCount":"1","teiki3Index":"3","teiki6Index":"3","timeOnBoard":"3","exhaustCO2":"41","fareIndex":"2","exhaustCO2atPassengerCar":"319","distance":"19","teiki1Index":"3","Name":"西武新宿線","Type":"train","ArrivalState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"TypicalName":"西武新宿線","TimeReliability":"none","DepartureState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"Color":"255238000"},{"direction":"Down","stopStationCount":"1","teiki3Index":"3","teiki6Index":"3","timeOnBoard":"4","exhaustCO2":"59","fareIndex":"3","exhaustCO2atPassengerCar":"453","distance":"27","teiki1Index":"3","Name":"JR山手線内回り","Type":"train","ArrivalState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"TypicalName":"JR山手線内回り","TimeReliability":"none","DepartureState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"Color":"045232013"}],"Point":[{"Station":{"code":"22671","Name":"高円寺","Type":"train","Yomi":"こうえんじ"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.39.10.89","lati":"35.42.7.59","longi_d":"139.653027","gcs":"tokyo","lati_d":"35.70211"}},{"Station":{"code":"22936","Name":"東中野","Type":"train","Yomi":"ひがしなかの"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.41.12.50","lati":"35.42.11.0","longi_d":"139.686806","gcs":"tokyo","lati_d":"35.703056"}},{"Station":{"code":"22844","Name":"中井","Type":"train","Yomi":"なかい"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.41.23.0","lati":"35.42.41.0","longi_d":"139.689722","gcs":"tokyo","lati_d":"35.711389"}},{"Station":{"code":"22790","Name":"高田馬場","Type":"train","Yomi":"たかだのばば"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.42.27.0","lati":"35.42.36.39","longi_d":"139.7075","gcs":"tokyo","lati_d":"35.710111"}},{"Station":{"code":"22741","Name":"新宿","Type":"train","Yomi":"しんじゅく"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.42.11.0","lati":"35.41.15.0","longi_d":"139.703056","gcs":"tokyo","lati_d":"35.6875"}}]}},{"searchType":"plain","dataType":"plain","SerializeData":"VkV4QaEByALDAqYBM6KyA6YBM6KyBJHCAUMAAAACpgEzorIDyAEBAgEDAQQBBwEIAQoCD0JEAAWVwQKlWI_BAqVZmMECpVlCwQKlcp7BAqVY1QaUwwEEAgEDwQGlAYXDAQQCAQPBAaUH5cMBBAIBA8EBpQSDwwEEAgUDwQEBB5TFAaYBM6K2A4EEgQUACADGAaYBM6K2AgEDgQSBBQAIAMYBpgEzorYCAgOBBIEFAAgAxgGmATOitgIDA4EEgQUACAAIlMQEAQUBB6RuCAHFAgEEAgUBB6UC0QgCxQICBAMFAQelAUgIA8UCAwQEBQIHAQlEk2uV4AmSwQMBwwEBAgIDAQ|RxQGVAAECAwQClMMBAAIAAwDDAQECAQMBwwECAgIDAsMBAwIDAwMDlMMBAAIAAwDDAQECAQMBwwECAgIDAsMBAwIDAwMEkgABBZIAAA**--T3221233232319:F3321122120:A23121141:--729dc5f661611fadd1bc319e082d09d7037025cc--0--0--0--337","Price":[{"kind":"FareSummary","Oneway":"440","Round":"880"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Fare","index":"1","selected":"true","Type":"Fare","Oneway":"160","Round":"320"},{"fareRevisionStatus":"none","toLineIndex":"3","fromLineIndex":"2","kind":"Fare","index":"2","selected":"true","Type":"Fare","Oneway":"280","Round":"560"},{"kind":"Teiki1Summary","Oneway":"15600"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Teiki1","index":"1","selected":"true","Type":"Teiki1","Oneway":"4850"},{"fareRevisionStatus":"none","toLineIndex":"3","fromLineIndex":"2","kind":"Teiki1","index":"2","selected":"true","Type":"Teiki1","Oneway":"10750"},{"kind":"Teiki3Summary","Oneway":"44470"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Teiki3","index":"1","selected":"true","Type":"Teiki3","Oneway":"13820"},{"fareRevisionStatus":"none","toLineIndex":"3","fromLineIndex":"2","kind":"Teiki3","index":"2","selected":"true","Type":"Teiki3","Oneway":"30650"},{"kind":"Teiki6Summary","Oneway":"81320"},{"fareRevisionStatus":"none","toLineIndex":"1","fromLineIndex":"1","kind":"Teiki6","index":"1","selected":"true","Type":"Teiki6","Oneway":"23260"},{"fareRevisionStatus":"none","toLineIndex":"3","fromLineIndex":"2","kind":"Teiki6","index":"2","selected":"true","Type":"Teiki6","Oneway":"58060"}],"Route":{"timeOther":"19","timeOnBoard":"10","exhaustCO2":"136","exhaustCO2atPassengerCar":"1041","distance":"62","timeWalk":"2","transferCount":"2","Line":[{"direction":"Up","stopStationCount":"1","teiki3Index":"1","teiki6Index":"1","timeOnBoard":"4","exhaustCO2":"72","fareIndex":"1","exhaustCO2atPassengerCar":"554","distance":"33","teiki1Index":"1","Name":"JR総武線","Type":"train","ArrivalState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"TypicalName":"JR総武線","TimeReliability":"none","DepartureState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"Color":"255222000"},{"direction":"Up","stopStationCount":"0","teiki3Index":"2","teiki6Index":"2","timeOnBoard":"2","exhaustCO2":"22","fareIndex":"2","exhaustCO2atPassengerCar":"168","distance":"10","teiki1Index":"2","Name":"都営大江戸線","Type":"train","ArrivalState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"TypicalName":"都営大江戸線","TimeReliability":"none","DepartureState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"Color":"255107107"},{"direction":"Up","stopStationCount":"1","teiki3Index":"2","teiki6Index":"2","timeOnBoard":"4","exhaustCO2":"41","fareIndex":"2","exhaustCO2atPassengerCar":"319","distance":"19","teiki1Index":"2","Name":"東京メトロ丸ノ内線(池袋-荻窪)","Type":"train","ArrivalState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"TypicalName":"東京メトロ丸ノ内線(池袋-荻窪)","TimeReliability":"none","DepartureState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"Color":"255002014"},{"direction":"Up","stopStationCount":"0","timeOnBoard":"2","exhaustCO2":"0","exhaustCO2atPassengerCar":"0","distance":"0","Name":"徒歩","Type":"walk","ArrivalState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"TypicalName":"徒歩","TimeReliability":"none","DepartureState":{"Type":"normal","Datetime":{"text":"2016-12-06","operation":"today"}},"Color":"230230230"}],"Point":[{"Station":{"code":"22671","Name":"高円寺","Type":"train","Yomi":"こうえんじ"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.39.10.89","lati":"35.42.7.59","longi_d":"139.653027","gcs":"tokyo","lati_d":"35.70211"}},{"Station":{"code":"22936","Name":"東中野","Type":"train","Yomi":"ひがしなかの"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.41.12.50","lati":"35.42.11.0","longi_d":"139.686806","gcs":"tokyo","lati_d":"35.703056"}},{"Station":{"code":"22850","Name":"中野坂上","Type":"train","Yomi":"なかのさかうえ"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.41.9.0","lati":"35.41.38.0","longi_d":"139.685833","gcs":"tokyo","lati_d":"35.693889"}},{"Station":{"code":"29342","Name":"新宿(東京メトロ)","Type":"train","Yomi":"しんじゅく"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.42.15.0","lati":"35.41.21.0","longi_d":"139.704167","gcs":"tokyo","lati_d":"35.689167"}},{"Station":{"code":"22741","Name":"新宿","Type":"train","Yomi":"しんじゅく"},"Prefecture":{"code":"13","Name":"東京都"},"GeoPoint":{"longi":"139.42.11.0","lati":"35.41.15.0","longi_d":"139.703056","gcs":"tokyo","lati_d":"35.6875"}}]}}]}}

まず、経路は下記のようになっています。


  1. 高円寺→新宿

  2. 高円寺→中野(東京都)→高田馬場→新宿

  3. 高円寺→東中野→新宿

  4. 高円寺→東中野→中井→高田馬場→新宿

  5. 高円寺→東中野→中野坂上→新宿(東京メトロ)→新宿

そして、もちろん先ほどのsortを使っていきます。

しかし、変数はオブジェクトになってしまっているため、これをそのままソートすることはできません。

たとえば、こんな感じで実行しようとしても「list.sort is not a function」と出てしまいます。

var list = JSON.parse(探索結果のJSON文字列);

list.sort(function (a, b) {
if (a > b) return 1;
if (a < b) return -1;
return 0;
});

困りましたね。

でも実は単にどれを見てソートするか、分かっていないことが原因です。

探索結果には金額や距離、時間など様々な要素がありますので、どの項目でソートするか、ちゃんと指定しなければなりません。

さらに、JSONをパースした際、list変数にResultSetが入りますが、ここがArrayでないことも原因です。


まずは、ソート対象となるArrayを特定する

結論としては ResultSet / Course がソート対象となる配列です。

また、配列かどうかわからない場合、instanceof を使うと便利です。

早速実装していきましょう。


乗り換え回数の少ない順にソートしてみる

ソート前の乗り換え回数の順番を確認してみましょう。

if (list.ResultSet.Course instanceof Array) {

var buffer = new Array();
for (var i = 0; i < list.ResultSet.Course.length; i++) {
buffer.push(list.ResultSet.Course[i].Route.transferCount);
}
alert(buffer.join(","));
}

経路のインデックスと乗り換え回数の対応は下記の通りです。


  1. 高円寺→新宿 0回

  2. 高円寺→中野(東京都)→高田馬場→新宿 1回

  3. 高円寺→東中野→新宿 1回

  4. 高円寺→東中野→中井→高田馬場→新宿 3回

  5. 高円寺→東中野→中野坂上→新宿(東京メトロ)→新宿 2回

※第二経路の中野は乗り入れのため乗り換え回数にカウントしません。

※第五経路の新宿(東京メトロ)~新宿間は徒歩移動のため、乗り換え回数にカウントしません。

そして、ソートの本体はこちらです。

if (list.ResultSet.Course instanceof Array) {

// ソートを追加
list.ResultSet.Course.sort(function (a, b) {
if (a.Route.transferCount > b.Route.transferCount) return 1;
if (a.Route.transferCount < b.Route.transferCount) return -1;
return 0;
});
var buffer = new Array();
for (var i = 0; i < list.ResultSet.Course.length; i++) {
buffer.push(list.ResultSet.Course[i].Route.transferCount);
}
alert(buffer.join(","));
}

ソートを実行した結果が下記です。


  1. 高円寺→新宿 0回

  2. 高円寺→中野(東京都)→高田馬場→新宿 1回

  3. 高円寺→東中野→新宿 1回

  4. 高円寺→東中野→中野坂上→新宿(東京メトロ)→新宿 2回

  5. 高円寺→東中野→中井→高田馬場→新宿 3回

4番目と5番目が入れ替わりました。

では次に金額でソートしてみます。


乗車券の安い順にソートしてみる

でも、ちょっと待ってください。

金額は Price 要素の中から見つける必要があります。

経路探索のレスポンス

また、乗車券は FareSummary なので ResultSet.Course.Price.FareSummary.Oneway としたいところなのですが、Price は配列になっていて、何番目に FareSummary があるか分かりません。

比較的新しいブラウザであれば indexOf を使う手もありますが、今回は互換性を考えて使わずに実装してみます。

ちなみに、今回は getFareSummary 関数を用意して金額を取得できるようにしてみました。


乗車券の金額を取得する関数を用意する

function getFareSummary(Course) {

if (Course.Price instanceof Array) {
for (var i = 0; i < Course.Price.length; i++) {
if (Course.Price[i].kind == "FareSummary") {
return parseInt(Course.Price[i].Oneway);
}
}
}
return 0;
}

if (list.ResultSet.Course instanceof Array) {

var buffer = new Array();
for (var i = 0; i < list.ResultSet.Course.length; i++) {
buffer.push(getFareSummary(list.ResultSet.Course[i]));
}
alert(buffer.join(","));
}

まずはソート前の金額を確認です。


  1. 高円寺→新宿 160円

  2. 高円寺→中野(東京都)→高田馬場→新宿 430円

  3. 高円寺→東中野→新宿 340円

  4. 高円寺→東中野→中井→高田馬場→新宿 610円

  5. 高円寺→東中野→中野坂上→新宿(東京メトロ)→新宿 440円

また、この関数を利用してソートを実装していきます。

if (list.ResultSet.Course instanceof Array) {

list.ResultSet.Course.sort(function (a, b) {
if (getFareSummary(a) > getFareSummary(b)) return 1;
if (getFareSummary(a) < getFareSummary(b)) return -1;
return 0;
});
var buffer = new Array();
for (var i = 0; i < list.ResultSet.Course.length; i++) {
buffer.push(getFareSummary(list.ResultSet.Course[i]));
}
alert(buffer.join(","));
}

そして、金額順のソート結果は下記になりました。


  1. 高円寺→新宿 160円

  2. 高円寺→東中野→新宿 340円

  3. 高円寺→中野(東京都)→高田馬場→新宿 430円

  4. 高円寺→東中野→中野坂上→新宿(東京メトロ)→新宿 440円

  5. 高円寺→東中野→中井→高田馬場→新宿 610円


複合の条件でソートしてみる

今度は所要時間も考慮してソートしてみることにします。

まずは、所要時間を求める関数を用意します。

function getTotalTime(Course) {

return parseInt(Course.Route.timeOnBoard) + parseInt(Course.Route.timeWalk) + parseInt(Course.Route.timeOther);
}

この関数を使って所要時間、金額、乗り換え回数を算出すると下記になります。


  1. 高円寺→新宿 12分 160円 0回

  2. 高円寺→中野(東京都)→高田馬場→新宿 21分 430円 1回

  3. 高円寺→東中野→新宿 26分 340円 1回

  4. 高円寺→東中野→中井→高田馬場→新宿 32分 610円 3回

  5. 高円寺→東中野→中野坂上→新宿(東京メトロ)→新宿 31分 440円 2回

では、今まで行ってきたソートをまとめます。


  • まずは乗車券が安い順にソート

  • 金額が同じだった場合は所要時間の短い順にソート

  • 金額も所要時間も同じだった場合は乗り換え回数の少ない順にソート

そして、ソート部分はこちらです。

list.ResultSet.Course.sort(function (a, b) {

if (getFareSummary(a) > getFareSummary(b) || getFareSummary(a) == getFareSummary(b) && getTotalTime(a) > getTotalTime(b) || getFareSummary(a) == getFareSummary(b) && getTotalTime(a) == getTotalTime(b) && a.Route.transferCount > b.Route.transferCount) return 1;
if (getFareSummary(a) < getFareSummary(b) || getFareSummary(a) == getFareSummary(b) && getTotalTime(a) < getTotalTime(b) || getFareSummary(a) == getFareSummary(b) && getTotalTime(a) == getTotalTime(b) && a.Route.transferCount < b.Route.transferCount) return -1;
return 0;
});

これを実行すると、きれいに並びました。


  1. 高円寺→新宿 12分 160円 0回

  2. 高円寺→東中野→新宿 26分 340円 1回

  3. 高円寺→中野(東京都)→高田馬場→新宿 21分 430円 1回

  4. 高円寺→東中野→中野坂上→新宿(東京メトロ)→新宿 31分 440円 2回

  5. 高円寺→東中野→中井→高田馬場→新宿 32分 610円 3回


まとめ

どうでしたか?

結構簡単に実装出来たと思います。

また、特急券を考慮したり、距離を考慮したり、複数の項目を組み合わせてソートしたりも出来ますし、駅すぱあと以外でも sort が使えることが分かっていただけたのではないでしょうか。