回答編集履歴

3

バグ修正ついでに説明追加

2021/10/10 18:26

投稿

jimbe
jimbe

スコア13219

test CHANGED
@@ -18,6 +18,48 @@
18
18
 
19
19
  Sample クラスを活用するようにしてみました。
20
20
 
21
+ 科目の表示順・追加等は Sample のコンストラクタで行ってください。
22
+
23
+ ex) ```Sample sample = new Sample("名前","国語","外国語","数学");```
24
+
25
+
26
+
27
+ 同一名のデータは、纏めます。
28
+
29
+ ex)
30
+
31
+ ```plain
32
+
33
+ 田中ゆうき,国語,80
34
+
35
+ 佐藤かつひこ,数学,50
36
+
37
+ 田中ゆうき,数学,30
38
+
39
+ 田中たくや,国語,60
40
+
41
+ ```
42
+
43
+ ```plain
44
+
45
+ | 名前 |国語|外国語|数学|
46
+
47
+ +-----------------------------+
48
+
49
+ |田中ゆうき | 80| | 30|
50
+
51
+ +-----------------------------+
52
+
53
+ |佐藤かつひこ| | | 50|
54
+
55
+ +-----------------------------+
56
+
57
+ |田中たくや | 60| | |
58
+
59
+ +-----------------------------+
60
+
61
+ ```
62
+
21
63
 
22
64
 
23
65
  ```java
@@ -40,7 +82,7 @@
40
82
 
41
83
  public static void main(String[] args) throws IOException {
42
84
 
43
- Sample sample = new Sample("名前","国語","数学");
85
+ Sample sample = new Sample("名前","国語","外国語","数学");
44
86
 
45
87
  File file = new File("Sample1.txt");
46
88
 
@@ -240,7 +282,7 @@
240
282
 
241
283
  if(i == nameIndex) {
242
284
 
243
- sj.add(String.format("%-"+maxWidth[i]+"s", s.name)); //名前=左詰め
285
+ sj.add(s.name + " ".repeat(maxWidth[i]-count(s.name))); //名前=左詰め
244
286
 
245
287
  } else if(s.hasScore(headerList.get(i))) {
246
288
 

2

コード追加

2021/10/10 18:26

投稿

jimbe
jimbe

スコア13219

test CHANGED
@@ -18,10 +18,6 @@
18
18
 
19
19
  Sample クラスを活用するようにしてみました。
20
20
 
21
- コンストラクタに渡す科目の位置に合わせて点数が表示されます。
22
-
23
- 国語と数学の間に外国語とか入れても大丈夫ですし、"田中ゆうき,数学,30" という行を追加すれば田中ゆうきさんの行に国語と数学の点数が並びます。
24
-
25
21
 
26
22
 
27
23
  ```java

1

コード追加

2021/10/10 18:07

投稿

jimbe
jimbe

スコア13219

test CHANGED
@@ -9,3 +9,277 @@
9
9
  表示する時に変数する場合は、 writeLine の //2列目以降を右寄せ の中での k のループの時点で、line[j] を出力するか空白を出力するかを判断するようにします。
10
10
 
11
11
  が、List をわざわざ 2次元配列にしているなどの構造から見て、読み込み時に変換したほうが良いと思います。
12
+
13
+
14
+
15
+ ----
16
+
17
+
18
+
19
+ Sample クラスを活用するようにしてみました。
20
+
21
+ コンストラクタに渡す科目の位置に合わせて点数が表示されます。
22
+
23
+ 国語と数学の間に外国語とか入れても大丈夫ですし、"田中ゆうき,数学,30" という行を追加すれば田中ゆうきさんの行に国語と数学の点数が並びます。
24
+
25
+
26
+
27
+ ```java
28
+
29
+ package teratail_java.q363724;
30
+
31
+
32
+
33
+ import java.io.*;
34
+
35
+ import java.nio.charset.StandardCharsets;
36
+
37
+ import java.nio.file.Files;
38
+
39
+ import java.util.*;
40
+
41
+
42
+
43
+ public class Sample {
44
+
45
+ public static void main(String[] args) throws IOException {
46
+
47
+ Sample sample = new Sample("名前","国語","数学");
48
+
49
+ File file = new File("Sample1.txt");
50
+
51
+ try(BufferedReader br = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8); ) {
52
+
53
+ for(String line; (line=br.readLine()) != null; ) {
54
+
55
+ String[] array = line.split(",");
56
+
57
+ sample.put(array[0], array[1], Integer.parseInt(array[2]));
58
+
59
+ }
60
+
61
+ sample.drawSheet();
62
+
63
+ } catch (IOException e) {
64
+
65
+ e.printStackTrace();
66
+
67
+ }
68
+
69
+ }
70
+
71
+
72
+
73
+ private List<String> headerList;
74
+
75
+ private int nameIndex;
76
+
77
+ private int[] maxWidth;
78
+
79
+ private Map<String,Student> studentMap = new HashMap<>();
80
+
81
+
82
+
83
+ private static class Student {
84
+
85
+ final int number;
86
+
87
+ final String name;
88
+
89
+ private final Map<String,Integer> scoreMap = new HashMap<>();
90
+
91
+ Student(int number, String name) {
92
+
93
+ this.number = number;
94
+
95
+ this.name = name;
96
+
97
+ }
98
+
99
+ void putScore(String subject, int score) {
100
+
101
+ scoreMap.put(subject, score);
102
+
103
+ }
104
+
105
+ boolean hasScore(String subject) {
106
+
107
+ return scoreMap.containsKey(subject);
108
+
109
+ }
110
+
111
+ int getScore(String subject) {
112
+
113
+ return scoreMap.get(subject);
114
+
115
+ }
116
+
117
+ }
118
+
119
+
120
+
121
+ Sample(String... header) {
122
+
123
+ headerList = Arrays.asList(header);
124
+
125
+
126
+
127
+ nameIndex = headerList.indexOf("名前");
128
+
129
+ if(nameIndex < 0) throw new IllegalArgumentException("'名前' がありません");
130
+
131
+
132
+
133
+ maxWidth = new int[headerList.size()];
134
+
135
+ for(int i=0; i<headerList.size(); i++) {
136
+
137
+ maxWidth[i] = count(headerList.get(i));
138
+
139
+ }
140
+
141
+ }
142
+
143
+
144
+
145
+ void put(String name, String subject, int score) {
146
+
147
+ Student s = studentMap.get(name);
148
+
149
+ if(s == null) {
150
+
151
+ s = new Student(studentMap.size()+1, name); //number は出現順にしておく
152
+
153
+ studentMap.put(name, s);
154
+
155
+ maxWidth[nameIndex] = Math.max(maxWidth[nameIndex], count(s.name));
156
+
157
+ }
158
+
159
+ s.putScore(subject, score);
160
+
161
+ int i = headerList.indexOf(subject);
162
+
163
+ if(i >= 0 && i != nameIndex) maxWidth[i] = Math.max(maxWidth[i], count(""+score));
164
+
165
+ }
166
+
167
+
168
+
169
+ void drawSheet() {
170
+
171
+ drawHeader();
172
+
173
+ drawRowSeparator();
174
+
175
+ studentMap.values().stream()
176
+
177
+ .sorted(Comparator.comparingInt(s -> s.number)) //number順に並び替え
178
+
179
+ .forEach(s -> { drawStudent(s); drawRowSeparator(); });
180
+
181
+ }
182
+
183
+
184
+
185
+ private void drawHeader() {
186
+
187
+ StringJoiner sj = new StringJoiner("|","|","|");
188
+
189
+ for(int i=0; i<headerList.size(); i++) {
190
+
191
+ sj.add(getCenteringString(headerList.get(i), maxWidth[i]));
192
+
193
+ }
194
+
195
+ System.out.println(sj.toString());
196
+
197
+ }
198
+
199
+
200
+
201
+ private String getCenteringString(String str, int width) {
202
+
203
+ int space = width - count(str);
204
+
205
+ int pre = space / 2;
206
+
207
+ int post = space - pre;
208
+
209
+ return " ".repeat(pre)+str+" ".repeat(post);
210
+
211
+ }
212
+
213
+
214
+
215
+ private String rowSeparator;
216
+
217
+ private void drawRowSeparator() {
218
+
219
+ if(rowSeparator == null) {
220
+
221
+ StringJoiner sj = new StringJoiner("-","+","+");
222
+
223
+ for(int i=0; i<maxWidth.length; i++) {
224
+
225
+ sj.add("-".repeat(maxWidth[i]));
226
+
227
+ }
228
+
229
+ rowSeparator = sj.toString();
230
+
231
+ }
232
+
233
+ System.out.println(rowSeparator);
234
+
235
+ }
236
+
237
+
238
+
239
+ private void drawStudent(Student s) {
240
+
241
+ StringJoiner sj = new StringJoiner("|","|","|");
242
+
243
+ for(int i=0; i<maxWidth.length; i++) {
244
+
245
+ if(i == nameIndex) {
246
+
247
+ sj.add(String.format("%-"+maxWidth[i]+"s", s.name)); //名前=左詰め
248
+
249
+ } else if(s.hasScore(headerList.get(i))) {
250
+
251
+ sj.add(String.format("%"+maxWidth[i]+"d", s.getScore(headerList.get(i)))); //得点=右詰め
252
+
253
+ } else {
254
+
255
+ sj.add(" ".repeat(maxWidth[i]));
256
+
257
+ }
258
+
259
+ }
260
+
261
+ System.out.println(sj.toString());
262
+
263
+ }
264
+
265
+
266
+
267
+ //英数字、カタカナ、ひらがな、漢字の文字コードを分類する
268
+
269
+ public static int count(String str) {
270
+
271
+ int count = 0;
272
+
273
+ for(char c : str.toCharArray()) {
274
+
275
+ count += Character.UnicodeBlock.of(c) == Character.UnicodeBlock.BASIC_LATIN ? 1 : 2;
276
+
277
+ }
278
+
279
+ return count;
280
+
281
+ }
282
+
283
+ }
284
+
285
+ ```