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

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

ただいまの
回答率

87.61%

js(jQuery)で、二組の値をチェックして、重複を抜き出したい【コード有り】

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,906

score 18

お世話になります。
現在、javascript学習中のエンジニアです。

タイトルのつけ方がかなり難しかったのですが、下記のような動きをするコードを書きたいです。
実装の方法がイメージできず、有識者の方々にお聞きしたいです<(_ _)>

やりたいこと

確認ボタンが押された際にチェック処理が発火し、
同姓同名の名前がフォームに入力されていたら、
重複する「姓」「名」の行を赤字にする。

〇 完成のイメージ

イメージ説明

× 現状のイメージ

イメージ説明

できなかったこと

同姓同名の行"だけ"を赤字にするのがとてもむずかしいです...。

下記のソースコードをみていただくとわかるのですが、
input[text]タグを取得し、総当たりでチェックすることで、
「重複があれば全てのフォームを赤字」にすることはできました。

「× 現状のイメージ」の例でいうと、
同姓同名は「佐藤太郎」だけですので、一行目と三行目を赤くしたいのですが、
二行目の「佐藤」も赤くなってしまいます...。

これをなんとか改善したいのですが、正直、どうすれよいのかさっぱりです。。

ソースコード

https://jsfiddle.net/Lwajozn9/8/
→ ここから飛べます

↑ このURLのページに飛ぶと、下記の画像のように、実際に動かしたり修正したりできます。
イメージ説明

ソースコード原文

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <form>
        <div id="row1">
            姓 : <input type="text" value="佐藤">
            名 : <input type="text" value="太郎">
            削除 : <input type="checkbox">
        </div>
        <div id="row2">
            姓 : <input type="text" value="佐藤">
            名 : <input type="text" value="花子">
            削除 : <input type="checkbox">
        </div>
        <div id="row3">
            姓 : <input type="text" value="佐藤">
            名 : <input type="text" value="太郎">
            削除 : <input type="checkbox">
        </div>
        <div id="row4">
            姓 : <input type="text" value="安藤">
            名 : <input type="text" value="良子">
            削除 : <input type="checkbox">
        </div>
        <button type="submit">確認</button>
    </form>
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
<script>
$('form').submit(function() {    

    $('input[type=text]').each(function(i) {
        var str = $(this).val();
        var chk = 0;
        $('input[type=text]').each(function(j) {
            var str2 = $(this).val();
            if ((str2 == str) && (i != j)) {
            chk = 1;
        }
        });
        if(chk != 0) {    
            $(this).css("color", "#F00");
        }
    });

   return false;
});
</script>
</body>
</html>

以上、どうかご教授を何卒よろしくお願いいたします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

checkベストアンサー

+1

きれいなコードにならなかった。

.error input {
    color: red;
}
$( 'form' ).submit( function() {
    $( '.error' ).removeClass( 'error' );
    var list = {}
    $( '[id^="row"]' ).each( function() { // 行ごとに氏名を処理して、それをオブジェクトに保存
        var res = '';
        $( 'input', this ).each( function() {
            res += $( this ).val();
        } );
        if ( !list[ res ] ) list[ res ] = [];
        list[ res ].push( $( this ).attr( 'id' ) ); // 同姓同名なら2件以上になる
    } );
    Object.values( list ).filter( v=> v.length > 1 ).forEach( e=> e.forEach( id=> {
        $( '#' + id ).addClass( 'error' ); // 行単位でクラスを付与する
    } ) );
    return false;
} );

動くサンプル:https://jsfiddle.net/p45dqs9f/1/


【Object.values() - JavaScript | MDN】
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/values

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

こんな感じにしてみました。

$('form').submit(function() {
  var targetList = $('div',this);
  var targetNameList = $.map(targetList, function(x){return $('input:eq(0)',x).val()+$('input:eq(1)',x).val()});

  $( $.grep(targetList, function(x){
    var targetName = $('input:eq(0)',x).val()+$('input:eq(1)',x).val();
    return targetNameList.indexOf(targetName) != targetNameList.lastIndexOf(targetName);          
  }) ).each(function(){
    $('input',this).css("color", "#F00");
  });

  return false;
});

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

<!DOCTYPE html>
<title>?</title>
<meta charset="utf-8">
<style>

</style>

<body>
<body>
    <form>
        <div id="row1">
            姓 : <input type="text" value="佐藤">
            名 : <input type="text" value="太郎">
            削除 : <input type="checkbox">
        </div>
        <div id="row2">
            姓 : <input type="text" value="佐藤">
            名 : <input type="text" value="花子">
            削除 : <input type="checkbox">
        </div>
        <div id="row3">
            姓 : <input type="text" value="佐藤">
            名 : <input type="text" value="太郎">
            削除 : <input type="checkbox">
        </div>
        <div id="row4">
            姓 : <input type="text" value="安藤">
            名 : <input type="text" value="良子">
            削除 : <input type="checkbox">
        </div>
        <div id="row5">
            姓 : <input type="text" value="加賀">
            名 : <input type="text" value="美紀子">
            削除 : <input type="checkbox">
        </div>
        <div id="row6">
            姓 : <input type="text" value="加賀美">
            名 : <input type="text" value="紀子">
            削除 : <input type="checkbox">
        </div>
        <button type="submit">確認</button>
    </form>


<script>

class A {
  constructor (d) {
    this.input = [...d.querySelectorAll ('input[type="text"]')];
    this.name = this.input.map (e => e.value).join (' ');
  }

  setColor (c = 'red') {
    this.input.forEach (e => e.style.color = c);
  }
}

const check = (es) =>
  [...es.reduce ((a, b, c) =>
    (a.has (c = b.name) ? a.get (c).push (b): a.set (c, [b]), a)
    , new Map).values ()
  ].reduce ((a,b)=> 1 < b.length ? [...a,...b]: a, []);

//__________

let
  q = 'form div[id^=row]',
  rows = [...document.querySelectorAll (q)].map (e => new A(e)),
  rst;

if (rst = check (rows))
  rst.forEach (e => e.setColor ());


</script>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

やる気が無いときの実装方法、検証用結合フォームを用意してそれでチェックを行う

<form>
        <div id="row1">
            姓 : <input name="fname" type="text" value="佐藤">
            名 : <input name="lname" type="text" value="太郎">
            削除 : <input type="checkbox">
            <input name="cname" type="hidden" value="佐藤 太郎">
        </div>
        <div id="row2">
            姓 : <input name="fname" type="text" value="佐藤">
            名 : <input name="lname" type="text" value="花子">
            削除 : <input type="checkbox">
            <input name="cname" type="hidden" value="佐藤 花子">
        </div>
        <div id="row3">
            姓 : <input name="fname" type="text" value="佐藤">
            名 : <input name="lname" type="text" value="太郎">
            削除 : <input type="checkbox">
            <input name="cname" type="hidden" value="佐藤 太郎">
        </div>
        <div id="row4">
            姓 : <input name="fname" type="text" value="安藤">
            名 : <input name="lname" type="text" value="良子">
            削除 : <input type="checkbox">
            <input name="cname" type="hidden" value="安藤 良子">
        </div>
        <button type="button" id="submit">確認</button>
</form>
function check() {
    var error = false;
    $("form [name=cname]").each(function(i,e){
        var value = $(this).val();
        var size  = $("form [name=cname][value="+value+"]").length;
        if (size > 1) {
            $(this).parent().find("[name=fname]").css("color", "#F00");
            $(this).parent().find("[name=lname]").css("color", "#F00");
            error = true;
        } else {
            $(this).parent().find("[name=fname]").css("color", "#000");
            $(this).parent().find("[name=lname]").css("color", "#000");
        }
    });
    return error;
}
$(function(){
    $(document).on("change", "[type=text]", function(){
        var parent = $(this).parent(); // tr
        var fname = parent.find("[name=fname]").val();
        var lname = parent.find("[name=lname]").val();
        parent.find("[name=cname]").val(fname + " " + lname);
    });
    $(document).on("change", "[type=text]", check);
    $(document).on("click", "#submit", check);

});

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

    var names = $('div[id^="row"]').map(function(index, element) {
        return { name: $(element).find('input[type="text"]').map(function() { return this.value; }).get(), elm: element };
    }).get();

    for (var i = 0; i < names.length - 1; i++) {
        var filter = names.filter(function(a) { return a.name[0] === names[i].name[0] && a.name[1] === names[i].name[1]; });
        if (filter.length > 1) {
            filter.forEach(function(a) { return $(a.elm).addClass('error'); });
        }
    }

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 87.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る