48388


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文ももっとスマートに書ければ書き直したい...）

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


CC BY-SA 4.0
2018-09-14T05:50:15.537
48384
2018-09-14T06:34:58.227
30065
question
javascript jquery
配列同士で後方一致しない要素を出力したい


処理内容を少し考えてみればわかりますが、「a全部×b全部」の総当たりをしないといけないので、メインの二重`for`ループはあまり「スマートに」しようが無い気がします。

後は一致しないものを表示する部分ですね。以下は単純に、一致したらフラグを立てて、最後にフラグが立っていない要素をまとめて表示する、なんてことをしています。

[code]

    const a = ["http://abc/","http://abc/def/","http://ghi/"];
    const b = ["/abc/","/def/","/jkl/"];
    
    //aと同じ長さで初期値が全部falseの配列を作る
    var aHasMatch = a.map(_ => false);
    //bと同じ長さで初期値が全部falseの配列を作る
    var bHasMatch = b.map(_ => false);
    
    for( let i in a ) {
        for( let j in b ) {
            if( a[i].endsWith(b[j]) ){
                console.log(a[i] +"と"+ b[j] +"はOK");
                aHasMatch[i] = true;
                bHasMatch[j] = true;
            }
        }
    }
    //aの中で対応するaHasMatchがfalseのものだけ集める
    var aDiff = a.filter((_, i) => !aHasMatch[i]);
    console.log("配列a内の差分："+aDiff.join(","));
    //bの中で対応するbHasMatchがfalseのものだけ集める
    var bDiff = b.filter((_, j) => !bHasMatch[j]);
    console.log("配列b内の差分："+bDiff.join(","));
[/code]

`const`や`let`を使っているので、それが大丈夫なら大抵大丈夫だろうとばかり、ブラウザの対応状況を調べずコードを書いちゃっているので、もしかしたらブラウザによっては(あなたの元のコードが動くものでも)動かないかもしれませんが、考え方としてはそのまま使えると思います。

(もっと「スマートに」書けるかもしれませんが、最近のJavaScriptには不慣れなので…。)

一つの例としてお試しください。


CC BY-SA 4.0
2018-09-14T06:25:53.347
48387
2018-09-14T06:25:53.347
13972
48384
answer


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


CC BY-SA 4.0
2018-09-14T06:29:29.010
48388
2018-09-14T06:34:58.227
2018-09-14T06:34:58.227
30079
30079
48384
answer