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

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

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

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

5回答

1724閲覧

配列内の重複要素を抜き出せません。

tetsuya19

総合スコア19

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

1グッド

0クリップ

投稿2016/08/02 16:54

ozakiと申します。以下の事象で困っています。
ご教授お願い致します。

###前提・実現したいこと
実現したいことは、配列内にある要素で
重複している値を表示させることです。
言語はPHPです。
実行環境は、オンラインサイトの
http://ideone.com/のphpです。
文法エラーは出ていませんが、予想外の表示が出ています。
現在アルゴリズムの勉強なので、あえて
PHPのarray_unique等、便利な関数は使わずに手作りのロジックで
表示させたいです。

###発生している問題・エラーメッセージ
重複していない配列内の要素まで、表示されてしまいます。

エラーメッセージ 実行時のエラーはありません。 ###該当のソースコード <?php $data[0]=50; $data[1]=20; $data[2]=79; $data[3]=98; $data[4]=45; $data[5]=120; $data[6]=60; $data[7]=50; $data[8]=45; $data[9]=120; for($i = 0; $i <= 9; $i++) { for($j = 1; $j <= 10; $j++) { if($data[$i] === $data[$j] ) { echo "同じ値がありました。"; echo $data[$i]; echo PHP_EOL; } } } ?>

###試したこと
if文が機能していないようなので、Web等で調べて
文法を確認してみましたが、原因がわかりませんでした。

###補足情報(言語/FW/ツール等のバージョンなど)
何故if文で判定しているはずなのに、重複していない値も
表示されてしまうのでしょうか?
本当に困り果てています。ご回答宜しくお願い致します。

該当ソースコードの実行結果は下記の通りです。

同じ値がありました。50
同じ値がありました。20
同じ値がありました。79
同じ値がありました。98
同じ値がありました。45
同じ値がありました。45
同じ値がありました。120
同じ値がありました。120
同じ値がありました。60
同じ値がありました。50
同じ値がありました。45
同じ値がありました。45
同じ値がありました。120
同じ値がありました。120

mpyw👍を押しています

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

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

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

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

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

guest

回答5

0

二重ループのロジックを学習したいというのが主眼でないなら別のやりかた

PHP

1<?php 2$a=[50,20,79,98,0,45,120,60,50,45,120]; 3$b=[]; 4foreach($a as $num){ 5 if(!isset($b[$num])) $b[$num]=0; 6 $b[$num]++; 7} 8foreach($b as $key=>$num){ 9 if($num>1) print "同じ値がありました。{$key}<br>"; 10} 11?>

投稿2016/08/03 01:10

yambejp

総合スコア114814

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

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

tetsuya19

2016/08/03 10:02

回答頂きまして、ありがとうございます。 foreach文とisetを使うと大分すっきりしたコードに出来るんですね。 大変勉強になりました。
guest

0

書いておられる書き方でなら、こうでは?

PHP

1// for($j = 1; $j <= 10; $j++) 2// ↓ 3 for($j = $i + 1; $j <= 9; $j++)

PHP

1echo PHP_EOL; 2break; // add

複数同じ値がある場合は別配列に「重複したもの」を入れるなどしないと、結果が2回以上表示されると思いますよ。
例:$data[8]=50; にしたら break; しても50が2回表示されることになるはず。

投稿2016/08/02 17:08

編集2016/08/02 18:48
kei344

総合スコア69407

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

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

tetsuya19

2016/08/03 09:59

回答頂きありがとうございました。 breakの使い方も参考になりました。
tetsuya19

2016/08/03 10:56

示して頂いたfor文中の$i + 1という書き方大変参考になりました。
guest

0

まず,PHPの配列は,要素数がNのとき,キーは0〜N-1となるので,ループ継続条件は原則的に<=ではなく<で書く癖をつけたほうがいいかと思います.(全ての場合においてあてはまりませんが,前から順番にカウントアップしていく場合はたいてい該当します)

さて,今回の問題ですが,走査すべき組み合わせはこうなります.これを参考に (i, j) をどう変化させればいいか考えてみてください.

(0, 1) (0, 2) (0, 3) (0, 4) (0, 5) (0, 6) (0, 7) (0, 8) (0, 9)
(1, 2) (1, 3) (1, 4) (1, 5) (1, 6) (1, 7) (1, 8) (1, 9)
(2, 3) (2, 4) (2, 5) (2, 6) (2, 7) (2, 8) (2, 9)
(3, 4) (3, 5) (2, 6) (2, 7) (2, 8) (3, 9)
(4, 5) (4, 6) (4, 7) (4, 8) (4, 9)
(5, 6) (5, 7) (5, 8) (5, 9)
(6, 7) (6, 8) (6, 9)
(7, 8) (7, 9)
(8, 9)

i = 0, 1, 2, 3, 4, 5, 6, 7, 8

i=0のとき
j = 1, 2, 3, 4, 5, 6, 7, 8, 9

i=1のとき
j = 2, 3, 4, 5, 6, 7, 8, 9

i=2のとき
j = 3, 4, 5, 6, 7, 8, 9

...

i=8のとき
j=9


【解答例】
模範解答寄りすぎかもしれないですが,参考程度に解答させていただきます.
(まだ考察の余地がありましたら↓は読まないでください…汗

php

1<?php 2 3// 配列の初期化 4$data = [50, 20, 79, 98, 45, 120, 50, 50, 45, 120]; 5// 配列長 6$size = count($data); 7// 重複内容を記録する連想配列 8// (キーと値,双方に「数値 => 数値」の形で格納する) 9$duplicates = []; 10 11// i = 0, 1, 2, 3, 4, 5, 6, 7, 8 (末尾は不要) 12for ($i = 0; $i < $size - 1; ++$i) { 13 // 例: i = 0 のとき 14 // j = 1, 2, 3, 4, 5, 6, 7, 8, 9 (先頭は不要) 15 for ($j = $i + 1; $j < $size; ++$j) { 16 // 重複が既に確定している $data[$i] については… 17 if (isset($duplicates[$data[$i]])) { 18 // $data[$j] についてのループを回す必要がないので全て無視 19 break; 20 } 21 // 両者の値が一致したとき… 22 if ($data[$i] === $data[$j]) { 23 // 「数値 => 数値」の形で格納する 24 $duplicates[$data[$i]] = $data[$i]; 25 // 見つかったことは確定でこれ以上探す必要は無いので残りは無視 26 break; 27 } 28 } 29} 30 31// 結果をコンマで結合して表示 32printf("全体: %s\n", implode(', ', $data)); 33printf("重複: %s\n", implode(', ', $duplicates)); 34 35/* 36全体: 50, 20, 79, 98, 45, 120, 50, 50, 45, 120 37重複: 50, 45, 120 38*/

投稿2016/08/02 18:44

編集2016/08/02 19:30
mpyw

総合スコア5223

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

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

tetsuya19

2016/08/03 10:00

非常に詳細な解答を頂きまして、ありがとうございました。 しかもコードに加えて、コメント文まで。。 非常に助かりました。また宜しくお願いします。
guest

0

ベストアンサー

if文は正しく動いてますよ。

for文の二重ループのさせ方がまずいです。
そのループのさせ方だとiとjの値が一致した時に同じ要素を比較して重複と判定されます。

iとjが同一値の時の工夫を加えるか、
ループの回し方自体を工夫しましょう。

###追記
先ほど回答した際には見逃してましたが、
2番目のループが10以下を継続条件としてるので、
配列への不正アクセスが発生する疑いがあります。

PHP

1// i = 0、j = 10のとき 2if(data[0] === data[10]) // data[10]は未初期化

こちらも合わせて直したほうが良いと思います。

投稿2016/08/02 17:06

編集2016/08/02 17:44
Panzer_vor

総合スコア1636

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

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

tetsuya19

2016/08/03 10:58 編集

大変素早い回答ありがとうございました。 説明頂いた内容もわかりやすく、とても勉強になりました。 ご指摘頂いた i と j が同一値の時の処理がどうやればいいか、ちょっと考え中です。。
guest

0

ご回答頂いた皆さん誠にありがとうございました。
特にkei344様のご提示頂いた下記ヒントで解決致しました。
for($j = $i + 1; $j <= 9; $j++)
参考までに修正完了したソースと実行結果を表示しておきます。

ソースコード

<?php $data[0]=50; $data[1]=20; $data[2]=79; $data[3]=98; $data[4]=45; $data[5]=120; $data[6]=60; $data[7]=50; $data[8]=45; $data[9]=120; $data[10]=0; for($i = 0; $i <= 9; $i++) { for($j = $i +1; $j < 10; $j++) { if($data[$i] === $data[$j] ) { echo "同じ値がありました。"; echo $data[$i]; echo PHP_EOL; } } } ?>

表示結果
Success time: 0.03 memory: 52480 signal:0
同じ値がありました。50
同じ値がありました。45
同じ値がありました。120

投稿2016/08/03 11:46

tetsuya19

総合スコア19

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

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

kei344

2016/08/03 11:49

回答欄でもコードブロックは使えますよ。 ```(バッククオート3つ)で囲み、前後に改行をいれるか、コードを選択して「</>」ボタンを押すとコードブロックになります。 とりあえず解決されたようでよかったです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問