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

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

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

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

11738閲覧

java CSVデータを読み込み、HashMap<String, <String, Integer>>に要素を追加したい。

soma21

総合スコア18

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2019/07/28 13:06

編集2019/07/29 01:08

CSVデータを一行ずつ読み込み一行を","で区切って配列に代入し、配列の[2](問題番号を表す)、[4](スコアを表す)、その問題番号[2]でそのスコア[4]の人数をHashMap<String, <String, Integer>>に追加していきたいのですが、

java

1HashMap<String, HashMap<String, Integer>> map = new HashMap<>(); //mapの宣言 2HashMap<String, Integer> scores = new HashMap<>(); 3File file = new File(args[0]); //引数のファイルの実体を作成 4 BufferedReader in = new BufferedReader(new FileReader(file)); 5String line; 6while((line = in.readLine()) != null){ //一行ずつファイルを読みこむ 7 String[] array = line.split(","); //1行をコンマで区切る 8 if(!map.containsKey(array[2]) || !map.get(array[2]).containsKey(array[4])){ 9 scores.put(array[4], 1); 10 map.put(array[2], scores); 11 System.out.println("問題番号:"+ array[2] + "スコア" + array[4] + "人数" + 1); 12 } 13 else{ 14 Integer number_p = map.get(array[2]).get(array[4]); 15 number_p += 1; 16 map.get(array[2]).put(array[4], number_p); 17 System.out.println("問題番号"+array[2] + "スコア"+array[4] + "人数"+number_p); 18 } 19 }

これで実行したところ、問題番号が変わっても1つ前の問題番号のスコアが反映されて人数がおかしくなります。
どのように書けば、HashMap<問題番号, <スコア, 人数>>を作ることができるのでしょうか。
教えていただきたいです。

↓追記です

java

1import java.io.*; 2import java.util.HashMap; 3import java.util.Map; 4import java.util.Objects; 5import java.util.ArrayList; 6public class ScoreAnalyzer2{ 7 public static void main(String args[]) throws IOException{ //mainメソッド 8 ScoreAnalyzer2 app = new ScoreAnalyzer2(); 9 app.run(args); 10 } 11 void run(String args[]) throws IOException{ //runメソッド 12 HashMap<String, HashMap<String, Integer>> map = new HashMap<>(); //mapの宣言 13 HashMap<String, Integer> map2 = new HashMap<>(); //スコアと0 14 15 ArrayList<String> list = new ArrayList<>(); 16 File file = new File(args[0]); //引数のファイルの実体を作成 17 BufferedReader in = new BufferedReader(new FileReader(file)); 18 String line; 19 while((line = in.readLine()) != null){ //一行ずつファイルを読みこむ 20 String[] array = line.split(","); //1行をコンマで区切る 21 if(!map.containsKey(array[2]) || !map.get(array[2]).containsKey(array[4])){ 22 HashMap<String, Integer> scores = new HashMap<>(); 23 scores.put(array[4], 1); 24 map.put(array[2], scores); 25 System.out.println("問題番号:"+ array[2] + "スコア" + array[4] + "人数" + 1); 26 } 27 else{ 28 Integer number_p = map.get(array[2]).get(array[4]); 29 number_p += 1; 30 map.get(array[2]).put(array[4], number_p); 31 System.out.println("問題番号"+array[2] + "スコア"+array[4] + "人数"+number_p); 32 } 33 } 34 }

最終的にはそれぞれの問題番号のスコアごとに割合も算出したいです。
2019/4/11 reading 1 24 10 9:30 9:31
2019/4/11 reading 1 102 10 9:30 9:40
2019/5/16 reading 5 96 8 9:03 9:09
2019/5/16 reading 5 117 10 9:03 9:07
2019/5/16 reading 5 44 10 9:03 9:09
2019/5/9 reading 4 37 8 9:02 9:09
2019/5/9 reading 4 56 6 9:02 9:07
2019/5/9 reading 4 114 8 9:02 9:10
2019/5/9 reading 4 58 8 9:03 9:10
2019/4/25 reading 3 59 8 9:00 9:12
2019/4/25 reading 3 144 6 9:03 9:11
2019/4/25 reading 3 107 8 9:07 9:13
2019/4/25 reading 3 74 2 9:11 9:14
2019/4/18 reading 2 73 2 9:00 9:13
2019/4/18 reading 2 105 8 9:00 9:10
2019/4/18 reading 2 96 6 9:00 9:07

データは一部抜粋です。

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

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

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

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

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

guest

回答1

0

ベストアンサー

scoresオブジェクトが共有されていることが問題です。
簡単な例だと、例えば次のようなコードで再現できます。

Java

1List<List<Integer>> listOfList = new ArrayList<>(); 2List<Integer> list = new ArrayList<>(); 3 4for(int i = 0; i < 3; ++i) { 5 list.add(i); 6 listOfList.add(list); 7} 8System.out.println(listOfList); // => [[0, 1, 2], [0, 1, 2], [0, 1, 2]]

これを避ける為には、毎度新たにオブジェクトを作るようにすれば良いです。

Java

1List<List<Integer>> listOfList = new ArrayList<>(); 2 3for(int i = 0; i < 3; ++i) { 4 List<Integer> list = new ArrayList<>(); 5 6 list.add(i); 7 listOfList.add(list); 8} 9System.out.println(listOfList); // => [[0], [1], [2]]

組んでみた

面白そうだったので、適宜ググりつつ書いてみました。

Java

1import java.io.IOException; 2 3import java.nio.file.Files; 4import java.nio.file.Paths; 5 6import java.util.HashMap; 7import java.util.Map; 8 9 10class Main { 11 public static void main(String[] args) throws IOException { 12 Map<Integer, Map<Integer, Integer>> map = new HashMap<>(); 13 14 15 var path = Paths.get("./data.csv"); 16 try(var in = Files.newBufferedReader(path)) { 17 18 while(true) { 19 var line = in.readLine(); 20 if(line == null) break; 21 22 Integer question, score; 23 { 24 var fields = line.split(","); 25 assert fields.length == 5: "ill-formed CSV"; 26 27 question = Integer.valueOf(fields[2]); 28 score = Integer.valueOf(fields[4]); 29 } 30 31 var inner = map.computeIfAbsent( 32 question, HashMap<Integer, Integer>::new 33 ); 34 inner.merge(score, 1, (v1, v2) -> v1 + v2); 35 } 36 } 37 38 for(var key: map.keySet()) { 39 System.out.printf("%d, %s\n", key, map.get(key)); 40 } 41 } 42}

もっとイケてる書き方をご存知の方は是非教えて下さい。

投稿2019/07/28 13:42

編集2019/07/28 14:52
LouiS0616

総合スコア35658

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

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

soma21

2019/07/28 15:23

回答ありがとうございます。 while文で回るたびに新たにマップを定義するということですか??
LouiS0616

2019/07/28 15:25

そうですね、一番単純な方法だとそうなります。 実際には必要になったタイミングだけ生成した方が無駄の少ないプログラムになるでしょう。
soma21

2019/07/28 16:24

if文の条件式がおかしいので正しく出力されないのですが、条件式はどのように書けばそれぞれの問題番号のスコアの人数をとることができますか? 何度もすみません。
swordone

2019/07/28 16:28

横からだけど、「正しく出力されない」原因がなぜ「if文の条件式がおかしい」ことだと思うのですか?
soma21

2019/07/28 16:33

コメントありがとうございます。 csvファイルの問題番号は同じ問題番号ごとになっていて、一種類目の問題番号を読み込むときはorの判定に入るのですが、二種類目の問題番号になる正しい判定がされずに人数が変わらないからです。
LouiS0616

2019/07/28 22:41

現状のコードと問題が再現する必要最小限の入力ファイルを質問本文に追記して下さい。
soma21

2019/07/29 01:15

追記しました。
LouiS0616

2019/07/29 06:27

array[2]用のMapは既に存在するけれど、それにarray[4]用のエントリが無い場合についての考慮が抜けています。 しかしこの辺りを抜けなく記述しようと思うと存外大変なので、次のように二つの独立した問題として取り扱うことをお勧めします。 ・ array[2]用のMapは既に存在するか?無い場合は作る。 ・ 内側のMapについて、array[4]用のエントリは存在するか?無い場合は作る。有る場合は値を更新する。
soma21

2019/07/30 15:19

ありがとうございます。試してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問