回答編集履歴
3
バグ修正ついでに説明追加
answer
CHANGED
@@ -8,7 +8,28 @@
|
|
8
8
|
----
|
9
9
|
|
10
10
|
Sample クラスを活用するようにしてみました。
|
11
|
+
科目の表示順・追加等は Sample のコンストラクタで行ってください。
|
12
|
+
ex) ```Sample sample = new Sample("名前","国語","外国語","数学");```
|
11
13
|
|
14
|
+
同一名のデータは、纏めます。
|
15
|
+
ex)
|
16
|
+
```plain
|
17
|
+
田中ゆうき,国語,80
|
18
|
+
佐藤かつひこ,数学,50
|
19
|
+
田中ゆうき,数学,30
|
20
|
+
田中たくや,国語,60
|
21
|
+
```
|
22
|
+
```plain
|
23
|
+
| 名前 |国語|外国語|数学|
|
24
|
+
+-----------------------------+
|
25
|
+
|田中ゆうき | 80| | 30|
|
26
|
+
+-----------------------------+
|
27
|
+
|佐藤かつひこ| | | 50|
|
28
|
+
+-----------------------------+
|
29
|
+
|田中たくや | 60| | |
|
30
|
+
+-----------------------------+
|
31
|
+
```
|
32
|
+
|
12
33
|
```java
|
13
34
|
package teratail_java.q363724;
|
14
35
|
|
@@ -19,7 +40,7 @@
|
|
19
40
|
|
20
41
|
public class Sample {
|
21
42
|
public static void main(String[] args) throws IOException {
|
22
|
-
Sample sample = new Sample("名前","国語","数学");
|
43
|
+
Sample sample = new Sample("名前","国語","外国語","数学");
|
23
44
|
File file = new File("Sample1.txt");
|
24
45
|
try(BufferedReader br = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8); ) {
|
25
46
|
for(String line; (line=br.readLine()) != null; ) {
|
@@ -119,7 +140,7 @@
|
|
119
140
|
StringJoiner sj = new StringJoiner("|","|","|");
|
120
141
|
for(int i=0; i<maxWidth.length; i++) {
|
121
142
|
if(i == nameIndex) {
|
122
|
-
sj.add(
|
143
|
+
sj.add(s.name + " ".repeat(maxWidth[i]-count(s.name))); //名前=左詰め
|
123
144
|
} else if(s.hasScore(headerList.get(i))) {
|
124
145
|
sj.add(String.format("%"+maxWidth[i]+"d", s.getScore(headerList.get(i)))); //得点=右詰め
|
125
146
|
} else {
|
2
コード追加
answer
CHANGED
@@ -8,8 +8,6 @@
|
|
8
8
|
----
|
9
9
|
|
10
10
|
Sample クラスを活用するようにしてみました。
|
11
|
-
コンストラクタに渡す科目の位置に合わせて点数が表示されます。
|
12
|
-
国語と数学の間に外国語とか入れても大丈夫ですし、"田中ゆうき,数学,30" という行を追加すれば田中ゆうきさんの行に国語と数学の点数が並びます。
|
13
11
|
|
14
12
|
```java
|
15
13
|
package teratail_java.q363724;
|
1
コード追加
answer
CHANGED
@@ -3,4 +3,141 @@
|
|
3
3
|
読んだ時に編集する場合は、 lineList.add(line.split(",")); で直接 lineList に入れているのを変えて、必要な構造で add するようにします。
|
4
4
|
|
5
5
|
表示する時に変数する場合は、 writeLine の //2列目以降を右寄せ の中での k のループの時点で、line[j] を出力するか空白を出力するかを判断するようにします。
|
6
|
-
が、List をわざわざ 2次元配列にしているなどの構造から見て、読み込み時に変換したほうが良いと思います。
|
6
|
+
が、List をわざわざ 2次元配列にしているなどの構造から見て、読み込み時に変換したほうが良いと思います。
|
7
|
+
|
8
|
+
----
|
9
|
+
|
10
|
+
Sample クラスを活用するようにしてみました。
|
11
|
+
コンストラクタに渡す科目の位置に合わせて点数が表示されます。
|
12
|
+
国語と数学の間に外国語とか入れても大丈夫ですし、"田中ゆうき,数学,30" という行を追加すれば田中ゆうきさんの行に国語と数学の点数が並びます。
|
13
|
+
|
14
|
+
```java
|
15
|
+
package teratail_java.q363724;
|
16
|
+
|
17
|
+
import java.io.*;
|
18
|
+
import java.nio.charset.StandardCharsets;
|
19
|
+
import java.nio.file.Files;
|
20
|
+
import java.util.*;
|
21
|
+
|
22
|
+
public class Sample {
|
23
|
+
public static void main(String[] args) throws IOException {
|
24
|
+
Sample sample = new Sample("名前","国語","数学");
|
25
|
+
File file = new File("Sample1.txt");
|
26
|
+
try(BufferedReader br = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8); ) {
|
27
|
+
for(String line; (line=br.readLine()) != null; ) {
|
28
|
+
String[] array = line.split(",");
|
29
|
+
sample.put(array[0], array[1], Integer.parseInt(array[2]));
|
30
|
+
}
|
31
|
+
sample.drawSheet();
|
32
|
+
} catch (IOException e) {
|
33
|
+
e.printStackTrace();
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
private List<String> headerList;
|
38
|
+
private int nameIndex;
|
39
|
+
private int[] maxWidth;
|
40
|
+
private Map<String,Student> studentMap = new HashMap<>();
|
41
|
+
|
42
|
+
private static class Student {
|
43
|
+
final int number;
|
44
|
+
final String name;
|
45
|
+
private final Map<String,Integer> scoreMap = new HashMap<>();
|
46
|
+
Student(int number, String name) {
|
47
|
+
this.number = number;
|
48
|
+
this.name = name;
|
49
|
+
}
|
50
|
+
void putScore(String subject, int score) {
|
51
|
+
scoreMap.put(subject, score);
|
52
|
+
}
|
53
|
+
boolean hasScore(String subject) {
|
54
|
+
return scoreMap.containsKey(subject);
|
55
|
+
}
|
56
|
+
int getScore(String subject) {
|
57
|
+
return scoreMap.get(subject);
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
Sample(String... header) {
|
62
|
+
headerList = Arrays.asList(header);
|
63
|
+
|
64
|
+
nameIndex = headerList.indexOf("名前");
|
65
|
+
if(nameIndex < 0) throw new IllegalArgumentException("'名前' がありません");
|
66
|
+
|
67
|
+
maxWidth = new int[headerList.size()];
|
68
|
+
for(int i=0; i<headerList.size(); i++) {
|
69
|
+
maxWidth[i] = count(headerList.get(i));
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
void put(String name, String subject, int score) {
|
74
|
+
Student s = studentMap.get(name);
|
75
|
+
if(s == null) {
|
76
|
+
s = new Student(studentMap.size()+1, name); //number は出現順にしておく
|
77
|
+
studentMap.put(name, s);
|
78
|
+
maxWidth[nameIndex] = Math.max(maxWidth[nameIndex], count(s.name));
|
79
|
+
}
|
80
|
+
s.putScore(subject, score);
|
81
|
+
int i = headerList.indexOf(subject);
|
82
|
+
if(i >= 0 && i != nameIndex) maxWidth[i] = Math.max(maxWidth[i], count(""+score));
|
83
|
+
}
|
84
|
+
|
85
|
+
void drawSheet() {
|
86
|
+
drawHeader();
|
87
|
+
drawRowSeparator();
|
88
|
+
studentMap.values().stream()
|
89
|
+
.sorted(Comparator.comparingInt(s -> s.number)) //number順に並び替え
|
90
|
+
.forEach(s -> { drawStudent(s); drawRowSeparator(); });
|
91
|
+
}
|
92
|
+
|
93
|
+
private void drawHeader() {
|
94
|
+
StringJoiner sj = new StringJoiner("|","|","|");
|
95
|
+
for(int i=0; i<headerList.size(); i++) {
|
96
|
+
sj.add(getCenteringString(headerList.get(i), maxWidth[i]));
|
97
|
+
}
|
98
|
+
System.out.println(sj.toString());
|
99
|
+
}
|
100
|
+
|
101
|
+
private String getCenteringString(String str, int width) {
|
102
|
+
int space = width - count(str);
|
103
|
+
int pre = space / 2;
|
104
|
+
int post = space - pre;
|
105
|
+
return " ".repeat(pre)+str+" ".repeat(post);
|
106
|
+
}
|
107
|
+
|
108
|
+
private String rowSeparator;
|
109
|
+
private void drawRowSeparator() {
|
110
|
+
if(rowSeparator == null) {
|
111
|
+
StringJoiner sj = new StringJoiner("-","+","+");
|
112
|
+
for(int i=0; i<maxWidth.length; i++) {
|
113
|
+
sj.add("-".repeat(maxWidth[i]));
|
114
|
+
}
|
115
|
+
rowSeparator = sj.toString();
|
116
|
+
}
|
117
|
+
System.out.println(rowSeparator);
|
118
|
+
}
|
119
|
+
|
120
|
+
private void drawStudent(Student s) {
|
121
|
+
StringJoiner sj = new StringJoiner("|","|","|");
|
122
|
+
for(int i=0; i<maxWidth.length; i++) {
|
123
|
+
if(i == nameIndex) {
|
124
|
+
sj.add(String.format("%-"+maxWidth[i]+"s", s.name)); //名前=左詰め
|
125
|
+
} else if(s.hasScore(headerList.get(i))) {
|
126
|
+
sj.add(String.format("%"+maxWidth[i]+"d", s.getScore(headerList.get(i)))); //得点=右詰め
|
127
|
+
} else {
|
128
|
+
sj.add(" ".repeat(maxWidth[i]));
|
129
|
+
}
|
130
|
+
}
|
131
|
+
System.out.println(sj.toString());
|
132
|
+
}
|
133
|
+
|
134
|
+
//英数字、カタカナ、ひらがな、漢字の文字コードを分類する
|
135
|
+
public static int count(String str) {
|
136
|
+
int count = 0;
|
137
|
+
for(char c : str.toCharArray()) {
|
138
|
+
count += Character.UnicodeBlock.of(c) == Character.UnicodeBlock.BASIC_LATIN ? 1 : 2;
|
139
|
+
}
|
140
|
+
return count;
|
141
|
+
}
|
142
|
+
}
|
143
|
+
```
|