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

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

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

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

Q&A

解決済

4回答

1641閲覧

JavaScript 変数内の重複したURLを取り除きたい

akatsuka1794

総合スコア6

JavaScript

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

0グッド

0クリップ

投稿2021/11/07 23:58

編集2021/11/08 00:13

変数内の重複したURLを取り除きたいです
結果として
こんにちはhttps://yahoo.co.jp/こんばんはおはようhttps://google.com/という形が変数に格納されてる状態にしたいです

下記まではできていますが、ここからどう処理していけばいいかわかりません
replaceなどを使うのか、だとしても1つ目は残し、それ以降を消すとか可能なんでしょうか

追記
当方初心者なのでアロー関数?とか、複雑なコードはわかりません
できれば、少し手を加えただけで実現できないかと考えていますが難しいでしょうか

<script> window.onload=function(){ s="こんにちはhttps://yahoo.co.jp/こんばんはhttps://yahoo.co.jp/おはようhttps://google.com/"; if(s.match(/(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)/gi)){ aa=s.match(/(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)/gi); a = new Set(aa); a = Array.from(a);//重複はなくなるがどうしたら元の変数を保持し、その中身の重複を消すのか? for(i=0;i<a.length;i++){ alert(a[i]);//https://yahoo.co.jp/ https://google.com/ } } } </script>
<script> window.onload=function(){ s="こんにちはhttps://yahoo.co.jp/こんばんはhttps://yahoo.co.jp/おはようhttps://google.com/"; if(s.match(/(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)/gi)){ aa=s.match(/(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)/gi); a = new Set(aa); a = Array.from(a); console.log(a); for(i=0;i<a.length;i++){ s=s.replace(a[i],"");//これだとこんにちはこんばんはhttps://yahoo.co.jp/おはようになってしまう } } alert(s);//こんにちはこんばんはhttps://yahoo.co.jp/おはよう } </script>

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

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

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

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

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

guest

回答4

0

ベストアンサー

当方初心者なのでアロー関数?とか、複雑なコードはわかりません

あっそー。じゃ、初心者脱出のお手伝いをさせてください。

javascript

1const s = "こんにちはhttps://yahoo.co.jp/こんばんはhttps://yahoo.co.jp/おはようhttps://google.com/ごきげんようhttps://google.com/さようならhttps://yahoo.co.jp/"; 2 3const regexp = /(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)/gi; 4 5const result = s.replace(regexp, (m, _1, _2, i) => s.indexOf(m) === i ? m : ''); 6 7console.log(result); 8 9

"こんにちはhttps://yahoo.co.jp/こんばんはおはようhttps://google.com/ごきげんようさようなら"

???? サンプル

追記

コメントからの

const s = "こんにちはhttps://yahoo.co.jp/\r\nこんばんはhttps://yahoo.co.jp/\r\nおはようhttps://google.com/\r\nごきげんようhttps://google.com/ さようならhttps://yahoo.co.jp/\r\n";

となって\r\n(改行コードがあった場合も)をURL含め削除するにはどうしたらいいでしょうか?

についてですが、先に回答したコードの正規表現に、以下のように

diff

1- const regexp = /(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)/gi; 2+ const regexp = /(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)(\r\n)?/gi;

末尾に (\r\n)? を追加しておいて、これにあわせてreplace に渡す関数を以下のように修正するとよいかと思います。

diff

1- const result = s.replace(regexp, (m, _1, _2, i) => s.indexOf(m) === i ? m : ''); 2+ const result = s.replace(regexp, (m, _1, _2, _3, i) => s.indexOf(m) === i ? m.trim() : '');

???? サンプル

投稿2021/11/08 00:56

編集2021/11/08 03:12
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

melian

2021/11/08 02:08

Great!
akatsuka1794

2021/11/08 02:11 編集

勉強させてください。。 const s = "こんにちはhttps://yahoo.co.jp/\r\nこんばんはhttps://yahoo.co.jp/\r\nおはようhttps://google.com/\r\nごきげんようhttps://google.com/ さようならhttps://yahoo.co.jp/\r\n"; となって\r\n(改行コードがあった場合も)をURL含め削除するにはどうしたらいいでしょうか? const result = s.replace(regexp, (m, _1, _2, i) => s.indexOf(m) === i+'\r\n' ? m : ''); で行けるかと思ったら、、、だめでした おわかりでしたら教えていただけると幸いです
退会済みユーザー

退会済みユーザー

2021/11/08 03:12

@melianさん  ありがとうございます m(_ _)m @akatsuka1794さん コメントありがとうございます。回答のほうに追記しました。
akatsuka1794

2021/11/08 03:37

ばっちりでした、、 現時点でアロー関数はわけわかりませんが、これから勉強します ありがとうございました
akatsuka1794

2021/11/10 23:30

お世話になります また教えていただきたいのですが 下記コードで重複した@***の1つ目以降を取り除きたいのですがうまく動いてくれません 結果としては「@a @abc @b あいうえお」が残る形にしたいのですが、どうしたらいいでしょうか? <script> window.onload=function(){ regexp=/@[A-Z0-9]+/ig; str="@a @abc @a @b あいうえお"; strA = str.replace(regexp, (m, _1, _2, _3, i) => str.indexOf(m) === i ? m.trim() : ''); alert(strA); } </script>
退会済みユーザー

退会済みユーザー

2021/11/11 06:33 編集

こんにちは まず、回答のほうに書いた修正後のコードのほうをおさらいしますと、 const result = s.replace(regexp, (m, _1, _2, _3, i) => s.indexOf(m) === i ? m.trim() : ''); で、replace の第二引数に与えている関数の引数( => の前のカッコの中)は m, _1, _2, _3, i という5個ですが、この中で、アンダーバーで始まるものを _1, _2, _3 と、3つ与えています。これがなぜ3つなのかといえば、replace の第一引数に与えている正規表現regexpが、 const regexp = /(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)(\r\n)?/gi; というものになっており、この regexp はキャプチャするための丸カッコのくくり (・・・) が以下のように3つあるからです。 (https?|ftp) (://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+) (\r\n) これらの (・・・) にマッチした部分が引数_1, _2, _3 に入ってきます。ちなみに変数名をアンダーバーで始めているのは、これらは関数本体で使用しない変数なので、慣習的にアンダーバーで始めています。 上記をふまえて、あらたにコメントからご質問の正規表現 regexp = /@[A-Z0-9]+/ig; は、キャプチャする丸カッコのくくりが無いです。 したがって、replace の第二引数に与えている関数の引数には、先のURLを取得するほうのreplaceで、第二引数に与えていた関数の引数 m, _1, _2, _3, i の、1, _2, _3 は、変数名の意図としては「正規表現に含まれるキャプチャの左から1番目、2番目、3番目 」というものですが、 regexp = /@[A-Z0-9]+/ig; にはキャプチャがないので、用をなさない引数になってしまいます。結論をいうと、正規表現が regexp = /@[A-Z0-9]+/ig; というキャプチャがないものになるのであれば、replace の第二引数に与えている関数の引数は m, _1, _2, _3, i ではなくて、ここから _1, _2, _3 を取り去った m, i だけでよいです。つまりreplace の第二引数に与える関数は (m, i) => str.indexOf(m) === i ? m.trim() : '' でうまくいくと思います。 詳細は、一度、以下をよく読んでおくことをおすすめします。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_function_as_a_parameter 上記の仕様で、p1, p2, ... と書いてある変数名を、関数本体で使わないので、先述のとおり慣習にならい、 _1, _2, _3 としています。
退会済みユーザー

退会済みユーザー

2021/11/11 04:23

補足 コメントからご質問の、 > regexp=/@[A-Z0-9]+/ig; > str="@a @abc @a @b あいうえお"; という場合に、 > strA = str.replace(regexp, (m, _1, _2, _3, i) => str.indexOf(m) === i ? m.trim() : ''); としたときに、replace の第二引数に与えている関数 (m, _1, _2, _3, i) => str.indexOf(m) === i ? m.trim() : '' の本体(=>の後)のほうの str.indexOf(m) === i ? m.trim() : '' では引数の変数 i を、三項演算子の条件部分で使っていますが、このときの i に受け取りたい想定のインデクスは、正規表現にキャプチャがないので、引数 _1 に入ってきます。ですから (m, _1, _2, _3, i) => str.indexOf(m) === i ? m.trim() : '' の関数本体のほうの i を _1 に修正して (m, _1, _2, _3, i) => str.indexOf(m) === _1 ? m.trim() : '' とすると意図通り動くことも確認すると、より理解が深まると思います。
退会済みユーザー

退会済みユーザー

2021/11/11 13:14

ログイン情報がわからなくなってしまったため、アカウント作りなおしました わざわざ丁寧に解説いただきありがとうございます 何度も読み直して理解していこうと思います
退会済みユーザー

退会済みユーザー

2021/11/13 00:09

お世話になります 以前書いていただきました、コードで URLが重複していた場合のみに、\r\n含め消すというソースだったと思うのですが、 重複していない場合も消される事がわかりました ↓ 重複していた場合のみ、\r\nがついていれば\r\nも、\r\nなければ重複したURLのみとしたい場合、どうしたらいいでしょうか・・・? <script> window.onload=function(){ s = "https://yahoo.co.jp/\r\nhttps://google.com/\r\n"; regexp = /(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)(\r\n)?/gi; s = s.replace(regexp, (m, _1, _2, _3, i) => s.indexOf(m) === i ? m.trim() : ''); console.log(s);//重複していないのに\r\nが消えている } </script>
退会済みユーザー

退会済みユーザー

2021/11/13 18:50

宜しければ回答いただけると幸いです><
退会済みユーザー

退会済みユーザー

2021/11/13 18:57

これでよかったかは、わかりませんが一応目的になりました。。。 <script> window.onload=function(){ s = "https://yahoo.co.jp/\r\nhttps://google.com/\r\n"; regexp = /(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)(\r\n)?/gi; s = s.replace(regexp, (m, _1, _2, _3, i) => s.indexOf(m) === i ? m.trim()+"\r\n" : ''); console.log(s);//重複していないのに\r\nが消えている } </script>
退会済みユーザー

退会済みユーザー

2021/11/13 19:05

こんにちは。 m.trim() の .trim() が不要だったかもしれません。 修正前 s = s.replace(regexp, (m, _1, _2, _3, i) => s.indexOf(m) === i ? m.trim() : ''); 修正後 s = s.replace(regexp, (m, _1, _2, _3, i) => s.indexOf(m) === i ? m : ''); 回答に書くコードは、質問にある入力例とそれに対する望ましい結果だけを見て作っているものですので、他の入力例だと、また望ましくない結果になることはあると思います。ぜひ今回のように自力で挑戦してみるとよいでしょう。
guest

0

わかりやすさ優先(?)で書いてみました。

JavaScript

1const s="こんにちはhttps://yahoo.co.jp/こんばんはhttps://yahoo.co.jp/おはようhttps://google.com/"; 2 3const urlpattern = /((?:https?|ftp)://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)/gi; 4 5const a = s.split(urlpattern); 6for(let i=0; i<a.length; i++){ 7 if(a[i].match(urlpattern) && a.indexOf(a[i])<i){ 8 a[i]=""; 9 } 10} 11const result=a.join("");

1.文字列をURLで配列に分割。URLも含めて。
2.配列要素を順に見て、URLであり、同じものがそれ以前にあれば、空文字列にする
3.配列を連結する

splitの際に正規表現を括弧で囲んでおくと、それも分割後に残ります。

投稿2021/11/08 03:11

otn

総合スコア85901

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

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

akatsuka1794

2021/11/08 03:38

このコードであれば私でも何とか理解できそうです。 ありがとうございます。
guest

0

判定しながらreplaceをループで処理してはどうでしょうか?

javascript

1const reg=/((?:https?|ftp)(?:://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+))(.+?)(\1)/gi; 2var txt=`こんにちはhttps://yahoo.co.jp/こんばんはhttps://yahoo.co.jp/おはようhttps://google.com/`; 3var res=txt; 4while(reg.test(res)){ 5 res=res.replace(reg,"$1$2"); 6} 7console.log(res);

投稿2021/11/08 00:40

yambejp

総合スコア116724

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

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

akatsuka1794

2021/11/08 02:05

(´_ _)ありがとうございます
akatsuka1794

2021/11/08 03:41

アロー関数はよくわからないという前提で提示してくださったにも関わらず、 ベストアンサーを選べず申し訳ありません。 目的の動作を確認できており、こちらもベストアンサーです。
guest

0

あるURLが最初に現れたときは削除しない、2回目以降に現れた場合は削除したいということは、URLにマッチしたときに少なくともマッチした場所も取得できないといけません。Stringmatch()では場所の取得ができないので、使えません。

matchAll()の戻り値でループして、SetにマッチしたURLが入っていない場合は入れる、入っていた場合は場所と長さを記録してリストに保存しておきます。そのリストを逆順に処理して、場所と長さを逆順に削り取ればよいです。

投稿2021/11/08 00:35

int32_t

総合スコア21695

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

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

akatsuka1794

2021/11/08 02:04

ありがとうございます…φ(´ー`*)
akatsuka1794

2021/11/08 04:07 編集

よくよく考えたら aa=s.match(/(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)/gi); a = new Set(aa); a = Array.from(a);//重複はなくなるがどうしたら元の変数を保持し、その中身の重複を消すのか? とか全く無意味な処理を考えていました もっと頭が良くなりたいです
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問