質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

803閲覧

配列に格納したデータを取り出したい

agneau

総合スコア4

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

1グッド

1クリップ

投稿2022/09/28 12:00

編集2022/09/29 10:54

前提

Google Bloggerを利用。投稿ページに関連記事を表示するため、特定のラベルが付いた投稿のデータを抽出加工しようと思っています。

特定のラベルが付いた投稿のデータを、コールバック関数でJSONデータとして受け取り、一部をオブジェクトとしてpushをつかって配列に追加しました

実現したいこと

格納したデータを取り出して重複処理をしたい

(配列に追加したオブジェクトのうち重複しているオブジェクトを削除したい)

現状

配列への追加が上手くいっていないのか、配列からデータを取り出すことができませんでした。(Array(0)となってしまう)

いろいろ調べましたが解決の糸口が見つかりません。

解決策をご教示いただけると大変助かります。

補足

重複処理の方法に特にこだわりはないのですが、

重複しているオブジェクトの削除は【Javascript】オブジェクトの配列をuniqueにする(重複を削除する)ときはfilterではなくMapオブジェクトを使う - Qiitaを利用しようと思いました。

該当のソースコード

javascript

1<script> 2const currentPost = "<data:post.url/>"; // いま開いているページ 3//<![CDATA[ 4 5let unit = []; // この変数にデータを格納したい 6 7function feedData(json) { 8 // コールバック関数を受け取る関数 9 for (let i = 0; i < json.feed.entry.length; i++) { 10 let jsonFeedEntry = json.feed.entry[i]; 11 12 for (let k = 0; k < jsonFeedEntry.link.length; k++) { 13 if (jsonFeedEntry.link[k].href != currentPost) { 14 let imageUrl = 15 "media$thumbnail" in jsonFeedEntry 16 ? jsonFeedEntry.media$thumbnail.url 17 : "NoImage"; 18 let unitObject = {}; 19 20 if (jsonFeedEntry.link[k].rel == "alternate") { 21 unitObject.title = jsonFeedEntry.title.$t; 22 unitObject.link = jsonFeedEntry.link[k].href; 23 unitObject.image = imageUrl; 24 25 unit.push(unitObject); 26 } 27 } 28 } 29 } 30} 31 32console.log(unit); 33 34const uniqUnit = Array.from( 35 new Map(unit.map((data) => [data.link, data])).values() // 回答をもとに修正 36); 37console.log(uniqUnit); // Array(0)となってしまう 38 39//]]> 40</script>

コールバック関数

<b:loop>はラベルの数だけループするBloggerのタグです

javascript

1<b:loop values='data:post.labels' var='label'> 2 3<script async='async' expr:src='"/feeds/posts/summary/-/" + data:label.name + "?alt=json-in-script&callback=feedData&max-results=10"' type='text/javascript'/> 4 5</b:loop>

JSON

JSONデータのサンプルです

json

1{ 2 "version": "1.0", 3 "encoding": "UTF-8", 4 "feed": { 5 "xmlns": "http://www.w3.org/2005/Atom", 6 "xmlns$openSearch": "http://a9.com/-/spec/opensearchrss/1.0/", 7 "xmlns$blogger": "http://schemas.google.com/blogger/2008", 8 "xmlns$georss": "http://www.georss.org/georss", 9 "xmlns$gd": "http://schemas.google.com/g/2005", 10 "xmlns$thr": "http://purl.org/syndication/thread/1.0", 11 "title": { 12 "type": "text", 13 "$t": "" 14 }, 15 "subtitle": { 16 "type": "html", 17 "$t": "" 18 }, 19 "link": [ 20 { 21 "rel": "http://schemas.google.com/g/2005#feed", 22 "type": "application/atom+xml", 23 "href": "https://sample.com/feeds/posts/summary" 24 }, 25 { 26 "rel": "alternate", 27 "type": "text/html", 28 "href": "https://sample.com/search/label/apple" 29 } 30 ], 31 "entry": [ 32 { 33 "title": { 34 "type": "text", 35 "$t": "appleとbanana" 36 }, 37 "summary": { 38 "type": "text", 39 "$t": "" 40 }, 41 "link": [ 42 { 43 "rel": "replies", 44 "type": "application/atom+xml", 45 "href": "https://sample.com/feeds/21/comments/default", 46 "title": "" 47 }, 48 { 49 "rel": "alternate", 50 "type": "text/html", 51 "href": "https://sample.com/2022/03/apple-and-banana.html", 52 "title": "appleとbanana" 53 } 54 ], 55 "media$thumbnail": { 56 "xmlns$media": "http://search.yahoo.com/mrss/", 57 "url": "https://....jpg", 58 "height": "72", 59 "width": "72" 60 }, 61 "thr$total": { 62 "$t": "0" 63 } 64 }, 65 { 66 "title": { 67 "type": "text", 68 "$t": "apple" 69 }, 70 "summary": { 71 "type": "text", 72 "$t": "" 73 }, 74 "link": [ 75 { 76 "rel": "replies", 77 "type": "application/atom+xml", 78 "href": "https://sample.com/feeds/61/comments/default", 79 "title": "" 80 }, 81 { 82 "rel": "alternate", 83 "type": "text/html", 84 "href": "https://sample.com/2022/01/apple.html", 85 "title": "apple" 86 } 87 ], 88 "media$thumbnail": { 89 "xmlns$media": "http://search.yahoo.com/mrss/", 90 "url": "https://....jpg", 91 "height": "72", 92 "width": "72" 93 }, 94 "thr$total": { 95 "$t": "0" 96 } 97 }, 98 { 99 "title": { 100 "type": "text", 101 "$t": "appleとbanana" 102 }, 103 "summary": { 104 "type": "text", 105 "$t": "" 106 }, 107 "link": [ 108 { 109 "rel": "replies", 110 "type": "application/atom+xml", 111 "href": "https://sample.com/feeds/45/comments/default", 112 "title": "" 113 }, 114 { 115 "rel": "alternate", 116 "type": "text/html", 117 "href": "https://sample.com/2022/02/apple-and-banana.html", 118 "title": "appleとbanana" 119 } 120 ], 121 "media$thumbnail": { 122 "xmlns$media": "http://search.yahoo.com/mrss/", 123 "url": "https://....jpg", 124 "height": "72", 125 "width": "72" 126 }, 127 "thr$total": { 128 "$t": "0" 129 } 130 } 131 ] 132 } 133} 134

発生している問題・エラーメッセージ

変数unitにデータが格納されていない?のか、uniqUnitArray(0)となります

デベロッパーツールのコンソールをみると

オブジェクトを受け取った配列unit

はじめは

Array(4)

となり、展開すると

Array(4) 0: {title: 'appleとbanana', link: 'https:...apple-banana.html', image: 'https:...jpg'} 1: {title: 'apple', link: 'https:...apple.html', image: 'https:...jpg'} 2: {title: 'appleとbanana', link: 'https:...apple-banana.html', image: 'https:...jpg'} 3: {title: 'banana', link: 'https:...banana.html', image: 'https:...jpg'} length: 4

ブラウザをリロードをすると[]が表示され展開すると下記のようになります。

[] 0: {title: 'appleとbanana', link: 'https:...apple-banana.html', image: 'https:...jpg'} 1: {title: 'apple', link: 'https:...apple.html', image: 'https:...jpg'} 2: {title: 'appleとbanana', link: 'https:...apple-banana.html', image: 'https:...jpg'} 3: {title: 'banana', link: 'https:...banana.html', image: 'https:...jpg'} length: 4

uniqUnitについては、はじめは

Array(0)

となり、展開すると

length: 0

ブラウザをリロードをすると[]が表示され展開するとlength: 0となります。

試したこと

こちらの状況→関数外で宣言し、関数内で要素をpushした配列が空の配列としてみなされる - スタック・オーバーフローと似ているような気がするので非同期が関係しているのかも?

と考えPromiseなどを自分なりに書いてみましたが、上手くいきませんでした。

Cocode👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2022/09/29 02:16 編集

jsonデータのサンプルを提示くださいjsonにはfeedやentryがどうなっているかわかりません もしくはjsonをどうやって受け取っているかですかね・・・非同期処理ならasync/awaitで クリアになるかもしれませんが
agneau

2022/09/29 10:55

質問内容にJSONデータのサンプルと、コールバック関数を追加しました。 よろしくお願いいたします。
guest

回答1

0

ベストアンサー

feedData関数を呼び出したあとに uniqUnit を作らないといけませんが、feedData関数を呼び出す前に uniqUnit を作っているため [] になってしまいます。
その後、feedData関数を呼び出しても unit だけが更新され、uniqUnit は更新されません。
uniqUnitを更新する処理も関数にして、feedData関数から呼び出してはいかがでしょうか。
処理を修正したコードを示しておきます。

js

1let unit = []; // この変数にデータを格納したい 2let uniqUnit = []; 3 4function feedData(json) { 5 for (let i = 0; i < json.feed.entry.length; i++) { 6 const jsonFeedEntry = json.feed.entry[i]; 7 const imageUrl = "media$thumbnail" in jsonFeedEntry 8 ? jsonFeedEntry.media$thumbnail.url 9 : "NoImage"; 10 for (let k = 0; k < jsonFeedEntry.link.length; k++) { 11 if (jsonFeedEntry.link[k].rel == "alternate") { 12 const unitObject = {}; 13 unitObject.title = jsonFeedEntry.title.$t; 14 unitObject.link = jsonFeedEntry.link[k].href; 15 unitObject.image = imageUrl; 16 unit.push(unitObject); 17 } 18 } 19 } 20 updateUniqUnit(); 21} 22 23function updateUniqUnit() { 24 console.log('unit:', unit); 25 uniqUnit = Array.from( 26 new Map(unit.map((data) => [data.link, data])).values() // 回答をもとに修正 27 ); 28 console.log('uniqUnit:', uniqUnit); // Array(0)となってしまう 29}

unit.map で key と value の配列にして Map を作ります。

diff

1- new Map(unit.map((data) => [data, data.link, data])).values() 2+ new Map(unit.map((data) => [data.link, data])).values()

js

1const unit = [ 2 {title: 'appleとbanana', link: 'https:...apple-banana.html', image: 'https:...jpg'}, 3 {title: 'apple', link: 'https:...apple.html', image: 'https:...jpg'}, 4 {title: 'appleとbanana', link: 'https:...apple-banana.html', image: 'https:...jpg'}, 5 {title: 'banana', link: 'https:...banana.html', image: 'https:...jpg'}, 6]; 7 8const uniqUnit = Array.from( 9 new Map(unit.map(data => [data.link, data])).values() 10); 11console.log(uniqUnit);

text:実行結果

1[ 2 { 3 title: 'appleとbanana', 4 link: 'https:...apple-banana.html', 5 image: 'https:...jpg' 6 }, 7 { 8 title: 'apple', 9 link: 'https:...apple.html', 10 image: 'https:...jpg' 11 }, 12 { 13 title: 'banana', 14 link: 'https:...banana.html', 15 image: 'https:...jpg' 16 } 17]

投稿2022/09/28 12:31

編集2022/09/29 11:40
shiracamus

総合スコア5406

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

agneau

2022/09/28 22:45

ご回答ありがとうございます。 ご回答をもとに Map を修正しました。 しかし残念ながら uniqUnit は Array(0) となってしまいました。 おそらく unit にデータが格納されていないのでは?と思い、質問内容を修正しました。 よろしくお願いいたします。
shiracamus

2022/09/28 23:08

unitはArray(4)ではなかった、ということですか? 回答したコードの実行結果を追記しましたが、unitがArray(4)でuniqUnitはArray(3)になりました。
shiracamus

2022/09/28 23:26 編集

気になるところがありました。 let unitObject = {}; は if (jsonFeedEntry.link[k].rel == "alternate") { の次の行った方がいいのでは? そうしないと、pushした内容が上書きされてしまいますよ。 それと、 let imageUrl = ""; と、変数宣言と "media$thumbnail" がなかったときの値を設定が必要かと思います。 さらに、 if ("media$thumbnail" in jsonFeedEntry) { の処理は、jsonFeedEntry.linkの数に影響しないので、内側ループ直前に行えばいいと思います。 let imageUrl = "media$thumbnail" in jsonFeedEntry " ? jsonFeedEntry["media$thumbnail"] : ""; とかにしてはいかがでしょうか?
agneau

2022/09/29 10:56

ご回答ありがとうございます。 はじめに、ご提示いただいたコードを単体で実行すると重複処理ができました。ありがとうございます。 しかし、ご提示いただいたコードを該当コードに適用するとuniqUnitはArray(0)となってしまいます。 >unitはArray(4)ではなかった、ということですか? コンソール上はunitはArray(4)(ブラウザをリロードすると [])です。 これは素人考えですが、重複処理をするMapが正常に動いているとなると、なんらかの原因でunitにデータが格納されていないか、格納されるまえにMapが走るのではと思っています。 また、気になるところのご指摘ありがとうございます。 変数の位置の見直し、宣言、条件演算子の使用などコードを見直してみました。(if ("media$thumbnail" in jsonFeedEntry) { の処理は今開いているページを除外する条件分岐を追加した関係上内側のループにしました) 回答が得やすくなるように情報を追加したり、質問内容をもう少し具体的にしてみました。 よろしくお願いいたします。
agneau

2022/09/29 12:22

ありがとうございます!! 希望通りの動作が実現しました。 上手くいかなかった理由も理解できてスッキリしました。 また、ご指摘いただいたコードの書き方についても理解が進みました。 繰り返しになりますがありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問