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

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

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

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

Q&A

解決済

2回答

2950閲覧

配列内部の重複を1つにまとめたいです。(合算)

daiti916

総合スコア17

PHP

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

0グッド

0クリップ

投稿2016/11/29 08:10

編集2016/11/29 09:05

###前提・実現したいこと
現在phpで、選手成績一覧を作成しています。
※ブラウザ上に全選手の成績一覧を表示し、よろしければCSVで保存という形です。

実現したいことは、選手の番号が重複している場合(配列内部で)は、成績を合算して表示したいのです。

###発生している問題・エラーメッセージ
発生している問題は、同じ番号、同じ名前の人が2回出てきてしまいます。
※データの内容は異なるため、データを合算したいです。

※配列の中身は以下のような形です。

array(7) { ["toban"]=> string(4) "4089" ["name"]=> string(12) "山田太郎" ["SG"]=> int(0) ["G1"]=> int(0) ["G2"]=> int(0) ["G3"]=> int(0) ["GN"]=> int(1) } array(7) { ["toban"]=> string(4) "3907" ["name"]=> string(9) "田中太郎" ["SG"]=> int(0) ["G1"]=> int(1) ["G2"]=> int(0) ["G3"]=> int(0) ["GN"]=> int(0) }array(7) { ["toban"]=> string(4) "3070" ["name"]=> string(12) "山本太郎" ["SG"]=> int(0) ["G1"]=> int(0) ["G2"]=> int(0) ["G3"]=> int(0) ["GN"]=> int(1) } array(7) { ["toban"]=> string(4) "4089" ["name"]=> string(12) "山田太郎" ["SG"]=> int(0) ["G1"]=> int(0) ["G2"]=> int(0) ["G3"]=> int(0) ["GN"]=> int(1) }

※山田太郎さんが2人いるのですが、tobanが重複していたら合算して、表示したいと思っています。
→同じtobanで名前がこのなる人は存在しません。

###現在(該当)のソースコード

// 結果配列 $result = array(); // 全ての要素について一つずつ取り出して実行する foreach ($xml as $x){ // キー名をセット $keyValue = $x->toban . $x->name; if (!isset($result[$keyValue])) { // 同じ toban, name の要素が存在しないので新たに設定する $result[$keyValue] = array( 'toban'=>preg_replace("/( | )/", "", $x->toban) , 'name'=>preg_replace("/( | )/", "", $x->name), 'SG'=>0, 'G1'=>0, 'G2'=>0, 'G3'=>0, 'GN'=>0, ); } if ($x->grade == 'SG') { $result[$keyValue]['SG']++; } elseif ($x->grade == 'GⅠ') { $result[$keyValue]['G1']++; } elseif ($x->grade == 'GⅡ') { $result[$keyValue]['G2']++; } elseif ($x->grade == 'GⅢ') { $result[$keyValue]['G3']++; } elseif ($x->grade == '一般') { $result[$keyValue]['GN']++; } print '<table border="1">'; print '<tr> '; print '<td> 登番 </td>'; print '<td> 選手名 </td>'; print '<td> SG回数 </td>'; print '<td> G1回数 </td>'; print '<td> G2回数 </td>'; print '<td> G3回数 </td>'; print '<td> 一般回数 </td>'; print '</tr>'; print '<tr>'; /* 登番 */ print'<td>' .$result[$keyValue]['toban'] .'</td>'; /*選手名 */ print'<td>' .$result[$keyValue]['name'] .'</td>'; /* SG */ print'<td>' .$result[$keyValue]['SG'] .'</td>'; /* GⅠ */ print'<td>' .$result[$keyValue]['G1'] .'</td>'; /* GⅡ */ print'<td>' .$result[$keyValue]['G2'] .'</td>'; /* GⅢ */ print'<td>' .$result[$keyValue]['G3'] .'</td>'; /* 一般 */ print'<td>' .$result[$keyValue]['GN'] .'</td>'; print '</tr>'; print '</table>';

になっています。

※解決したいことが、tobanが重複している選手のデータを合算して表示したいです。

よろしければアドバイスをお願い致します。

※現在のブラウザ上に表示される画面です。
イメージ説明

●追記:全コード●

<?php //★覧取得★ if($xml = @file_get_contents("WEB上のURL")){ $xml = simpleXML_load_string($xml); $xml = (array)($xml->table); $xml = (array)($xml["record"]); } ?> <!doctype html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>csvファイル</title> <style> table { border-collapse: collapse; } td { border: 1px solid #333; text-align:center; } </style> </head> <body> <?php echo "<b>【↓内容はこちら↓】</b><hr><br>";?> <?php ``` // 結果配列 $result = array(); // 全ての要素について一つずつ取り出して実行する foreach ($xml as $x){ // キー名をセット $keyValue = $x->toban . $x->name; if (!isset($result[$keyValue])) { // 同じ toban, name の要素が存在しないので新たに設定する $result[$keyValue] = array( 'toban'=>preg_replace("/( | )/", "", $x->toban) , 'name'=>preg_replace("/( | )/", "", $x->name), 'SG'=>0, 'G1'=>0, 'G2'=>0, 'G3'=>0, 'GN'=>0, ); } if ($x->grade == 'SG') { $result[$keyValue]['SG']++; } elseif ($x->grade == 'GⅠ') { $result[$keyValue]['G1']++; } elseif ($x->grade == 'GⅡ') { $result[$keyValue]['G2']++; } elseif ($x->grade == 'GⅢ') { $result[$keyValue]['G3']++; } elseif ($x->grade == '一般') { $result[$keyValue]['GN']++; } /*確認用*/ print '<pre>'; var_dump($result[$keyValue]); print '</pre>'; print '<table border="1">'; print '<tr> '; print '<td> 登番 </td>'; print '<td> 選手名 </td>'; print '<td> SG回数 </td>'; print '<td> G1回数 </td>'; print '<td> G2回数 </td>'; print '<td> G3回数 </td>'; print '<td> 一般回数 </td>'; print '</tr>'; print '<tr>'; /* 登番 */ print'<td>' .$result[$keyValue]['toban'] .'</td>'; /*選手名 */ print'<td>' .$result[$keyValue]['name'] .'</td>'; /* SG */ print'<td>' .$result[$keyValue]['SG'] .'</td>'; /* GⅠ */ print'<td>' .$result[$keyValue]['G1'] .'</td>'; /* GⅡ */ print'<td>' .$result[$keyValue]['G2'] .'</td>'; /* GⅢ */ print'<td>' .$result[$keyValue]['G3'] .'</td>'; /* 一般 */ print'<td>' .$result[$keyValue]['GN'] .'</td>'; print '</tr>'; print '</table>'; } ?> </body> </html>

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

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

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

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

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

date

2016/11/29 08:20

成績一覧のデータはどこから取り出しているのですか?
daiti916

2016/11/29 08:32

WEBサーバ上においてあるXMLから参照しています。
kei344

2016/11/29 08:47

コードはそれぞれコードブロックで囲んでいただけませんか? ```(バッククオート3つ)で囲み、前後に改行をいれるか、コードを選択して「<code>」ボタンを押すとコードブロックになります。
daiti916

2016/11/29 08:59

追記で今のコードを載せました。 ```をで囲むと、Parse error: syntax error, unexpected '`' in とエラーが出てしまいます・・・
kei344

2016/11/29 09:02

言葉足らずですみません、「質問文の」コードです。実際のコードではなく、teratailの質問文編集画面での話です。
daiti916

2016/11/29 09:05

kei344>意図が読み取れずにすみません・・・。どうでしょうか?
guest

回答2

0

ベストアンサー

PHP

1$result = array(); 2foreach($xml as $x) { 3 $toban = preg_replace("/( | )/", "", $x->toban); 4 $name = preg_replace("/( | )/", "", $x->name); 5 if (!array_key_exists($toban, $result)) { 6 // toban の要素が存在しないので新たに設定する 7 $result[$toban] = array('toban'=>'', 'name'=>'', 8 'SG'=>0, 'G1'=>0, 'G2'=>0, 'G3'=>0, 'GN'=>0); 9 } 10 $result[$toban]['toban'] = $toban; 11 $result[$toban]['name'] = $name; 12 $result[$toban]['SG'] += $x->SG; 13 $result[$toban]['G1'] += $x->G1; 14 $result[$toban]['G2'] += $x->G2; 15 $result[$toban]['G3'] += $x->G3; 16 $result[$toban]['GN'] += $x->GN; 17}

で、集計はできるけど、これでは正しくないのかな? 意図がよくわからない。

投稿2016/11/29 09:11

編集2016/11/29 09:15
tacsheaven

総合スコア13703

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

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

daiti916

2016/11/30 01:14 編集

$result = array(); // 全ての要素について一つずつ取り出して実行する foreach ($xml as $x){ $toban = preg_replace("/( | )/", "", $x->toban); $name = preg_replace("/( | )/", "", $x->name); if (!array_key_exists($toban, $result)) { // 同じ tobanの要素が存在しないので新たに設定する $result[$toban] = array( 'toban'=>'', 'name'=>'', 'SG'=>0, 'G1'=>0, 'G2'=>0, 'G3'=>0, 'GN'=>0, ); } $result[$toban]['toban'] = $toban; $result[$toban]['name'] = $name; $result[$toban]['SG'] += $x->SG; $result[$toban]['G1'] += $x->G1; $result[$toban]['G2'] += $x->G2; $result[$toban]['G3'] += $x->G3; $result[$toban]['GN'] += $x->GN; print '<table border="1">'; print '<tr> '; print '<td> 登番 </td>'; print '<td>  選手名  </td>'; print '<td> SG回数 </td>'; print '<td> G1回数 </td>'; print '<td> G2回数 </td>'; print '<td> G3回数 </td>'; print '<td> 一般回数 </td>'; print '</tr>'; print '<tr>'; /* 登番 */ print'<td>' .$result[$toban]['toban'] .'</td>'; /*選手名 */ print'<td>' .$result[$toban]['name'] .'</td>'; /* SG */ print'<td>' .$result[$toban]['SG'] .'</td>'; /* GⅠ */ print'<td>' .$result[$toban]['G1'] .'</td>'; /* GⅡ */ print'<td>' .$result[$toban]['G2'] .'</td>'; /* GⅢ */ print'<td>' .$result[$toban]['G3'] .'</td>'; /* 一般 */ print'<td>' .$result[$toban]['GN'] .'</td>'; print '</tr>'; print '</table>'; } 現在上記のように修正したのですが、SG~GNまで全ての値が0になってしまうのと、tobanも同じもの(重複)してしまっています・・・。 ※XMLを編集する前は、このような感じでXMLに記載されています。 array(4) { [0]=> object(SimpleXMLElement)#4 (3) { ["toban"]=> string(4) "4089" ["name"]=> string(18) "山田  太郎" ["grade"]=> string(6) "一般" } [1]=> object(SimpleXMLElement)#5 (3) { ["toban"]=> string(4) "3907" ["name"]=> string(18) "田中  太郎" ["grade"]=> string(6) "GⅠ" } [2]=> object(SimpleXMLElement)#6 (3) { ["toban"]=> string(4) "3070" ["name"]=> string(18) "山本  太郎"" ["grade"]=> string(6) "一般" } [3]=> object(SimpleXMLElement)#7 (3) { ["toban"]=> string(4) "4089" ["name"]=> string(18) "山田  太郎" ["grade"]=> string(6) "一般" } } ●追記● 選手の年間の成績データを管理したいのが目的です。 同じ選手が、それぞれのグレード(SG,G1,G2,G3,一般)で優勝したとしまして、年間でこの選手はSG何回優勝し、一般を何回優勝しているのだろう。と確認したいです。 伝わりずらくて申し訳ございません・・・。
tacsheaven

2016/11/30 01:42 編集

foreach は $result[$toban]['GN'] += $x->GN; の次で終了してないと(printする前に全ての $result を集計を終わらせる)意味がありませんよ? その上で、「もう一度」$result をループして出力させるのです。
daiti916

2016/11/30 02:16

ありがとうございます。 現在↓ $result = array(); // 全ての要素について一つずつ取り出して実行する foreach ($xml as $x){ $toban = preg_replace("/( | )/", "", $x->toban); $name = preg_replace("/( | )/", "", $x->name); if (!array_key_exists($toban, $result)) { // 同じ tobanの要素が存在しないので新たに設定する $result[$toban] = array( 'toban'=>'', 'name'=>'', 'SG'=>0, 'G1'=>0, 'G2'=>0, 'G3'=>0, 'GN'=>0, ); } $result[$toban]['toban'] = $toban; $result[$toban]['name'] = $name; $result[$toban]['SG'] += $x->SG; $result[$toban]['G1'] += $x->G1; $result[$toban]['G2'] += $x->G2; $result[$toban]['G3'] += $x->G3; $result[$toban]['GN'] += $x->GN; } for($i=0; $i<15; $i++){ print '<table border="1">'; print '<tr> '; print '<td> 登番 </td>'; print '<td>  選手名  </td>'; print '<td> SG回数 </td>'; print '<td> G1回数 </td>'; print '<td> G2回数 </td>'; print '<td> G3回数 </td>'; print '<td> 一般回数 </td>'; print '</tr>'; print '<tr>'; /* 登番 */ print'<td>' .$result[$toban]['toban'] .'</td>'; /*選手名 */ print'<td>' .$result[$toban]['name'] .'</td>'; /* SG */ print'<td>' .$result[$toban]['SG'] .'</td>'; /* GⅠ */ print'<td>' .$result[$toban]['G1'] .'</td>'; /* GⅡ */ print'<td>' .$result[$toban]['G2'] .'</td>'; /* GⅢ */ print'<td>' .$result[$toban]['G3'] .'</td>'; /* 一般 */ print'<td>' .$result[$toban]['GN'] .'</td>'; print '</tr>'; print '</table>'; } ここまで修正したのですが、同じ人のデータしか表示されないです。
tacsheaven

2016/11/30 02:29

それは当然ですね。foreach の後の for ループで、$i は変化していますけど、どの $i のときも、同じ $toban のデータを出しているのですから。(表のヘッダ部分も同じ回数出てますね) foreach($xml as $x) のループが終了した時点で、$result に何がどう入っているのか。そしてそれを表の形に出力するには、まず何を出力して、何をループさせながら出力させればよいのか、今一度よく考えてみましょう。
daiti916

2016/11/30 04:24

$resultを確認致しました。 まず、tobanごとに変数に入れ、その変数をループさせながら値を変えていけばよいと考えています。 ですが、foreach($xml as $x) のループが終了した時点で、$result を出力したのですが、 成績データ(SG,G1,G2,G3,GN)には0の値しか入っていませんでした。
guest

0

まるまる書くとこうなりますけれど、どこがおかしいのでしょうね。

PHP

1<!-- test.php --> 2<?php 3 class xml { 4 public $toban; 5 public $name; 6 public $SG; 7 public $G1; 8 public $G2; 9 public $G3; 10 public $GN; 11 12 function __construct($toban, $name, $SG, $G1, $G2, $G3, $GN) { 13 $this->toban = $toban; 14 $this->name = $name; 15 $this->SG = $SG; 16 $this->G1 = $G1; 17 $this->G2 = $G2; 18 $this->G3 = $G3; 19 $this->GN = $GN; 20 } 21 } 22 23 $xml = array( 24 new xml('4089','山田太郎', 0, 0, 0, 0, 1), 25 new xml('3907','田中太郎', 0, 0, 1, 0, 0), 26 new xml('3070','山本太郎', 0, 0, 0, 0, 1), 27 new xml('4089','山田太郎', 0, 0, 0, 0, 1), 28 ); 29 30 $result = array(); 31 foreach($xml as $x) { 32 if (!array_key_exists($x->toban, $result)) { 33 $result[$x->toban] = array('toban'=>$x->toban, 'name' => $x->name, 'SG'=>0, 'G1'=>0, 'G2'=>0, 'G3'=>0, 'GN' => 0); 34 } 35 $result[$x->toban]['SG'] += $x->SG; 36 $result[$x->toban]['G1'] += $x->G1; 37 $result[$x->toban]['G2'] += $x->G2; 38 $result[$x->toban]['G3'] += $x->G3; 39 $result[$x->toban]['GN'] += $x->GN; 40 } 41 42 foreach(array_keys($result) as $key) { 43 print $result[$key]['toban'] . ' '; 44 print $result[$key]['name'] . ' '; 45 print $result[$key]['SG'] . ' '; 46 print $result[$key]['G1'] . ' '; 47 print $result[$key]['G2'] . ' '; 48 print $result[$key]['G3'] . ' '; 49 print $result[$key]['GN'] . ' '; 50 print "\r\n"; 51 } 52?>

結果
$ php test.php
4089 山田太郎 0 0 0 0 2
3907 田中太郎 0 0 1 0 0
3070 山本太郎 0 0 0 0 1

投稿2016/11/30 05:23

tacsheaven

総合スコア13703

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

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

daiti916

2016/11/30 06:09

ご丁寧にありがとうございます>_< 重複データはなくなりました!・・・が成績データがゼロになってしまいます泣 ●ソースコード <?php //一覧取得 if($xml = @file_get_contents("WEB上のURL")){ $xml = simpleXML_load_string($xml); $xml = (array)($xml->table); $xml = (array)($xml["record"]); } class xml { public $toban; public $name; public $SG; public $G1; public $G2; public $G3; public $GN; function __construct($toban, $name, $SG, $G1, $G2, $G3, $GN) { $this->toban = $toban; $this->name = $name; $this->SG = $SG; $this->G1 = $G1; $this->G2 = $G2; $this->G3 = $G3; $this->GN = $GN; } } ?> <!doctype html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>csvファイル</title> <style> table { border-collapse: collapse; } td { border: 1px solid #333; text-align:center; } </style> </head> <body> <?php echo "<b>【↓内容はこちら↓】</b><hr><br>";?> <?php // 結果配列 $result = array(); // 全ての要素について一つずつ取り出して実行する foreach ($xml as $x){ $toban = preg_replace("/( | )/", "", $x->toban); $name = preg_replace("/( | )/", "", $x->name); if (!array_key_exists($toban, $result)) { // 同じ tobanの要素が存在しないので新たに設定する $result[$toban] = array( 'toban'=>$x->toban, 'name'=>$x->name, 'SG'=>0, 'G1'=>0, 'G2'=>0, 'G3'=>0, 'GN'=>0, ); } $result[$toban]['SG'] += $x->SG; $result[$toban]['G1'] += $x->G1; $result[$toban]['G2'] += $x->G2; $result[$toban]['G3'] += $x->G3; $result[$toban]['GN'] += $x->GN; } foreach(array_keys($result) as $key) { print '<table border="1">'; print '<tr> '; print '<td> 登番 </td>'; print '<td>  選手名  </td>'; print '<td> SG回数 </td>'; print '<td> G1回数 </td>'; print '<td> G2回数 </td>'; print '<td> G3回数 </td>'; print '<td> 一般回数 </td>'; print '</tr>'; print '<tr>'; /* 登番 */ print'<td>' .$result[$key]['toban'] .'</td>'; /*選手名 */ print'<td>' .$result[$key]['name'] .'</td>'; /* SG */ print'<td>' .$result[$key]['SG'] .'</td>'; /* GⅠ */ print'<td>' .$result[$key]['G1'] .'</td>'; /* GⅡ */ print'<td>' .$result[$key]['G2'] .'</td>'; /* GⅢ */ print'<td>' .$result[$key]['G3'] .'</td>'; /* 一般 */ print'<td>' .$result[$key]['GN'] .'</td>'; print '</tr>'; print '</table>'; } ?> </body> </html> XMLの中身を再度確認したところ↓ array(71) { [0]=> object(SimpleXMLElement)#4 (16) { ["hdate"]=> string(8) "20161002" ["jcd"]=> string(2) "01" ["jname"]=> string(9) "※値" ["toban"]=> string(4) "4089" ["name"]=> string(18) "※山田  太郎" ["grade"]=> string(6) "一般" ["rsname"]=> string(54) "※レース場" ["rno"]=> string(2) "12" ["kimari"]=> string(9) "差 し" ["sdate"]=> string(8) "20161031" ["fdate"]=> string(8) "20160928" ["tdate"]=> string(8) "20161002" ["nj"]=> string(2) "05" ["sflg"]=> string(1) "1" ["ktitl"]=> string(54) "※クラブカップ" ["gcd"]=> string(1) "4" } ※は個人情報に近いので、別の値にしております。 この中で必要なのは、["toban"],["name"],["grade"](gradeは、SG,G1,G2,G3,一般に分かれています。)になります。 お手数ですが、宜しくお願い致します。
tacsheaven

2016/11/30 06:14

XML に何が入っていて、$xml にどう入っていて、それをどう集計するか($result[$toban]['SG'] をどうカウントするか)という部分で、データ構造と実装とで食い違いがあるからです。 その XML のとおりならば、$x->grade が何かによって、$result[$toban]['SG']~$result[$toban]['GN']のいずれかを一つカウントアップする、という作業になりますよ?
daiti916

2016/11/30 06:19

tacsheaven様 以前作成していたものと、tacsheaven様に作成していただいたものをマージしたら理想の形になりました! あとは、これをCSV保存できるようにするのみになりました。 大変助かりました・・・。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問