配列同士で後方一致しない要素を出力したい


a,b ２つの配列のそれぞれの要素が後方一致するかを比較し、

  * a,b両方で存在したもの（後方一致）
  * aの配列内でbに無い要素（後方一致しないもの）
  * bの配列内でaに無い要素（後方一致しないもの）

をそれぞれ出力したいです。

出力例としてはこんな感じにしたい

[code]

    const a = ["http://abc/","http://abc/def/","http://ghi/"];
    const b = ["/abc/","/def/","/jkl/"];
    /*
    出力例:
    http://abc/ と /abc/ はOK
    http://abc/def/ と /def/はOK
    配列a内の差分：http://ghi/
    配列b内の差分：/jkl/
    */
    
[/code]

自分で書いてみたところ、a[0]とb全部→a[1]とb全部→...という風に、  
後方一致するものの出力はできました。

[code]

    for(let i=0;i<a.length;i++){
        for(let j=0;j<b.length;j++){
            if(a[i].endsWith(b[j])){
                console.log(a[i] +"と"+ b[j] +"はOK");
            }
        }
    }
    /*
    出力:
    http://abc/ と /abc/ はOK
    http://abc/def/ と /def/はOK
    */
    
[/code]

aの配列内でbと後方一致しないもの（<http://ghi/>）  
bの配列内でaと後方一致しないもの（/jkl/）  
をどう出力すれば良いかわかりません。

何かいい方法があれば教えていただきたいです。  
（上記のfor文ももっとスマートに書ければ書き直したい...）

ご回答の程、よろしくお願いします。




> aの配列内でbと後方一致しないもの（<http://ghi/>）

これは、aの要素それぞれに対して、bの要素と後方一致するかどうかを調べて、どれとも一致しないものだけを表示することでできます。  
一番分かりやすい方法は、フラグ変数を用いてbのどれかの要素と一致したかを調べるという方法でしょう。これをやってみると次のプログラムのようになります。

[code]

    for(let i=0;i<a.length;i++){
        // フラグ変数（bの要素のどれかと一致したらfalseにする）
        let flag = true;
        for(let j=0;j<b.length;j++){
            if(a[i].endsWith(b[j])){
                flag = false;
            }
        }
        // bの各要素を調べ終わった後にflagがまだtrueなら、
        // これはaの配列内でbに無い要素だ
        if (flag) {
            console.log("配列a内の差分:" + a[i]);
        }
    }
    
[/code]

> bの配列内でaと後方一致しないもの（/jkl/）

これも同じアイデアで可能です。ただし、ループの順番を変えて、bの各要素に対してループして、その中でaの各要素を調べるという形にすればよいでしょう。

[code]

    for(let i=0;i<b.length;i++){
        // フラグ変数（aの要素のどれかと一致したらfalseにする）
        let flag = true;
        for(let j=0;j<a.length;j++){
            if(a[j].endsWith(b[i])){
                flag = false;
            }
        }
        // aの各要素を調べ終わった後にflagがまだtrueなら、
        // これはbの配列内でaに無い要素だ
        if (flag) {
            console.log("配列b内の差分:" + b[i]);
        }
    }
    
[/code]

* * *

また、よりスマートに書く方法をいくつか紹介します。最後の例については、フラグ変数`flag`をいちいち持っておくのが嫌なので、ラベル付きfor文と`continue`文を用いて次のように書き直せます。

[code]

    outerLoop: for(let i=0;i<b.length;i++){
        for(let j=0;j<a.length;j++){
            if(a[j].endsWith(b[i])){
                // aの要素と一致したのでこのbの要素を調べるのはやめる
                continue outerLoop;
            }
        }
        // bの各要素を調べ終わっても生き残ったので、
        // これはaの配列内でbに無い要素だ
        console.log("配列b内の差分:" + b[i]);
    }
    
[/code]

また、2重for文は分かりにくいので、[Array#every](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/every)を用いて次のように書き直すこともできます。

[code]

    for(let i=0;i<b.length;i++){
        if (a.every(aElm => !aElm.endsWith(b[i]))) {
            // aの要素のどれとも後方一致しなかったら
            console.log("配列b内の差分:" + b[i]);
        }
    }
    
[/code]

一番最初の例については2重for文を書かないといけないのは仕方ありませんが、普通のfor文の代わりにfor-
of文を使うと少し分かりやすくなるので紹介します。

[code]

    for(let aElm of a){
        for(let bElm of b){
            if(aElm.endsWith(bElm)){
                console.log(aElm +"と"+ bElm +"はOK");
            }
        }
    }
    
[/code]




> aの配列内でbと後方一致しないもの（<http://ghi/>）

これは、aの要素それぞれに対して、bの要素と後方一致するかどうかを調べて、どれとも一致しないものだけを表示することでできます。  
一番分かりやすい方法は、フラグ変数を用いてbのどれかの要素と一致したかを調べるという方法でしょう。これをやってみると次のプログラムのようになります。

[code]

    for(let i=0;i<a.length;i++){
        // フラグ変数（bの要素のどれかと一致したらfalseにする）
        let flag = true;
        for(let j=0;j<b.length;j++){
            if(a[i].endsWith(b[j])){
                flag = false;
            }
        }
        // bの各要素を調べ終わった後にflagがまだtrueなら、
        // これはaの配列内でbに無い要素だ
        if (flag) {
            console.log("配列a内の差分:" + a[i]);
        }
    }
    
[/code]

> bの配列内でaと後方一致しないもの（/jkl/）

これも同じアイデアで可能です。ただし、ループの順番を変えて、bの各要素に対してループして、その中でaの各要素を調べるという形にすればよいでしょう。

[code]

    for(let i=0;i<b.length;i++){
        // フラグ変数（aの要素のどれかと一致したらfalseにする）
        let flag = true;
        for(let j=0;j<a.length;j++){
            if(a[j].endsWith(b[i])){
                flag = false;
            }
        }
        // aの各要素を調べ終わった後にflagがまだtrueなら、
        // これはbの配列内でaに無い要素だ
        if (flag) {
            console.log("配列b内の差分:" + b[i]);
        }
    }
    
[/code]

* * *

また、よりスマートに書く方法をいくつか紹介します。最後の例については、フラグ変数`flag`をいちいち持っておくのが嫌なので、ラベル付きfor文と`continue`文を用いて次のように書き直せます。

[code]

    outerLoop: for(let i=0;i<b.length;i++){
        for(let j=0;j<a.length;j++){
            if(a[j].endsWith(b[i])){
                // aの要素と一致したのでこのbの要素を調べるのはやめる
                continue outerLoop;
            }
        }
        // bの各要素を調べ終わっても生き残ったので、
        // これはaの配列内でbに無い要素だ
        console.log("配列b内の差分:" + b[i]);
    }
    
[/code]

また、2重for文は分かりにくいので、[Array#every](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/every)を用いて次のように書き直すこともできます。

[code]

    for(let i=0;i<b.length;i++){
        if (a.every(aElm => !aElm.endsWith(b[i]))) {
            // aの要素のどれとも後方一致しなかったら
            console.log("配列b内の差分:" + b[i]);
        }
    }
    
[/code]

一番最初の例については2重for文を書かないといけないのは仕方ありませんが、普通のfor文の代わりにfor-
of文を使うと少し分かりやすくなるので紹介します。

[code]

    for(let aElm of a){
        for(let bElm of b){
            if(aElm.endsWith(bElm)){
                console.log(aElm +"と"+ bElm +"はOK");
            }
        }
    }
    
[/code]

