【Java】行の量増し
解決済
回答 2
投稿
- 評価
- クリップ 0
- VIEW 1,093

退会済みユーザー
こんにちは、知恵を貸していただきたいです
以下のようなデータを取得してきます
ブック作成キー 行キー 行VALUE 行数
B001 K001 V001 1
B001 K002 V002 2
B001 K003 V003 3
B001 K003 V004 3
B001 K004 V005 1
B001 K005 V006 2
B002 K006 V007 3
B002 K007 V008 1
B002 K008 NULL 2
B002 K009 V009 4
B002 K010 V010 1
この表を元に以下のような行数を量増しした表を取得したいです
・ブック作成キー・行キーはユニークな値のキーセット
・行VALUEには行数以下の数の値が紐づく(ない場合もある)
・行数分の行のうち、行VALUEをまず出力して
行数 ー 紐づく行VALUEの数分、行VALUEが空の行を複製する
・これをJavaのみで実現する
最終形
ブック作成キー 行キー 行VALUE 行数
B001 K001 V001 1
B001 K002 V002 2
B001 K002 NULL 2
B001 K003 V003 3
B001 K003 NULL 3
B001 K003 NULL 3
B001 K003 V004 3
B001 K003 NULL 3
B001 K003 NULL 3
B001 K004 V005 1
B001 K005 V006 2
B001 K005 NULL 2
B002 K006 V007 3
B002 K006 NULL 3
B002 K006 NULL 3
B002 K007 V008 1
B002 K008 NULL 2
B002 K008 NULL 2
B002 K009 V009 4
B002 K009 NULL 4
B002 K009 NULL 4
B002 K009 NULL 4
B002 K010 V010 1
ループさせてなんやかんやが激しく苦手なので
どなたかご教授願います
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
check解決した方法
0
ご回答・質問内容へのご指摘をいただきまして、ありがとうございます
今朝スッキリした頭で再考し冗長気味ではございますが解決しましたので
自己解決とさせていただきます
説明不足で申し訳なかったのですが
入力値の取得に使用しているクエリが複雑で修正コストが高そうな上
出力の際に件数分ループさせるだけでいいようなリストを作成することが目的でした
簡単にまとめると
1:ブックキー単位の出力データリストは既に作成されている
2:その中で各出力データリストに指定の条件で行をコピーして追加する
3:Javaだけでという縛り
この3点を満たそうとして混乱してしまいました
ご協力に感謝します
本当にありがとうございます
前提が少し間違っていましたので訂正します
・行キーがブレークするまで出力
・行キーがブレークしたタイミングで行数分の行VALUE空値な行をコピーして出力
以下ソースと結果を記載します
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AddRowLoopSample {
/**
* @param args
*/
public static void main(String[] args) {
//入力値
//実際は某SELECTで取得した結果
String[][] inArr = {
{"B001","K001","V001","1"}
,{"B001","K002","V002","2"}
,{"B001","K003","V003","3"}
,{"B001","K003","V004","3"}
,{"B001","K004","V005","1"}
,{"B001","K005","V006","2"}
,{"B002","K006","V007","3"}
,{"B002","K007","V008","1"}
,{"B002","K008","","2"}
,{"B002","K009","V009","4"}
,{"B002","K010","V010","1"}
};
//各BOOKKEYごとのデータにまとめる
//ロジックあり
Map<String, List<Row>> res = new HashMap<String, List<Row>>();
for(String[] elem: inArr){
Row row = new Row();
row.setBookKey(elem[0]);
row.setRowKey(elem[1]);
row.setRowValue(elem[2]);
row.setRowCnt(elem[3]);
List<Row> replaceList = new ArrayList<Row>();
if(res.containsKey(elem[0])){
replaceList = res.get(elem[0]);
}
replaceList.add(row);
res.put(elem[0], replaceList);
}
//行KEYごとに行数分の行を作成
//ロジックなし・・・この部分がわからなかったです
for(Map.Entry<String, List<Row>> book : res.entrySet()){
List<Row> tempList = new ArrayList<Row>();
Row prevRow = new Row();
boolean isFirst = true;
for(Row row: book.getValue()){
if(isFirst){
tempList.add(row);
isFirst = false;
}else{
if(!prevRow.getRowKey().equals(row.getRowKey())){
tempList.add(row);
for(int i = 0;i < Integer.parseInt(row.getRowCnt());i++){
tempList.add(getCopyRow(row));
}
}
}
prevRow = row;
}
//最終行について
for(int i = 0;i < Integer.parseInt(prevRow.getRowCnt());i++){
tempList.add(getCopyRow(prevRow));
}
//作り終わったリストを入れ替える
res.put(book.getKey(), tempList);
}
//出力結果確認
//実際はBOOKKEY分のEXCELファイルを作成
//中のシートにMapのValueに格納しているリスト分の行を出力
for(Map.Entry<String, List<Row>> book : res.entrySet()){
for(Row row: book.getValue()){
System.out.println(row.getBookKey() + " " + row.getRowKey() + " " + row.getRowValue() + " " + row.getRowCnt());
}
}
}
private static Row getCopyRow(Row row){
Row ret = new Row();
ret.setBookKey(row.getBookKey());
ret.setRowKey(row.getRowKey());
ret.setRowValue("");
ret.setRowCnt(row.getRowCnt());
return ret;
}
}
public class Row {
private String bookKey;
private String rowKey;
private String rowValue;
private String rowCnt;
public String getBookKey() {
return bookKey;
}
public void setBookKey(String bookKey) {
this.bookKey = bookKey;
}
public String getRowKey() {
return rowKey;
}
public void setRowKey(String rowKey) {
this.rowKey = rowKey;
}
public String getRowValue() {
return rowValue;
}
public void setRowValue(String rowValue) {
this.rowValue = rowValue;
}
public String getRowCnt() {
return rowCnt;
}
public void setRowCnt(String rowCnt) {
this.rowCnt = rowCnt;
}
}
出力結果
B001 K001 V001 1
B001 K002 V002 2
B001 K002 2
B001 K002 2
B001 K003 V003 3
B001 K003 3
B001 K003 3
B001 K003 3
B001 K004 V005 1
B001 K004 1
B001 K005 V006 2
B001 K005 2
B001 K005 2
B001 K005 2
B001 K005 2
B002 K006 V007 3
B002 K007 V008 1
B002 K007 1
B002 K008 2
B002 K008 2
B002 K008 2
B002 K009 V009 4
B002 K009 4
B002 K009 4
B002 K009 4
B002 K009 4
B002 K010 V010 1
B002 K010 1
B002 K010 1
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
アルゴリズムとしては恐らく以下のようなものをお考えなのではないかと思います。
ただすでに指摘されている通り、これだけだと入出力フォーマットを合わせるところで躓かれるのではと心配します。例えば、必要とされているのが SQL だったりすればほぼすべて書き直しになってしまいます。
少しでも助けになれば良いのですが。。。
https://paiza.io/projects/AebEAJapmAXcJnza0ms3Jg
public class Main {
public static void main(String[] args) throws Exception {
String input =
"B001 K001 V001 1\n" +
"B001 K002 V002 2\n" +
"B001 K003 V003 3\n" +
"B001 K003 V004 3\n" +
"B001 K004 V005 1\n" +
"B001 K005 V006 2\n" +
"B002 K006 V007 3\n" +
"B002 K007 V008 1\n" +
"B002 K008 NULL 2\n" +
"B002 K009 V009 4\n" +
"B002 K010 V010 1\n";
// 行で分割
String[] lines = input.split("\n", 0);
for (int i = 0; i < lines.length; i++) {
// 1つ以上の空白文字で分割
// items[0] : ブック作成キー
// items[1] : 行キー
// items[2] : 行VALUE
// items[3] : 行数
String[] items = lines[i].split(" +", 0);
// 行数を数値に直す
int row_count = Integer.parseInt(items[3]);
// 行数分だけ出力する
// 始めの行 (row==0) では行キーを、それ以降では NULL を、
// 空白4文字区切りで出力する
for(int row = 0; row < row_count; row++) {
System.out.println(
items[0] + " " +
items[1] + " " +
(row == 0 ? items[2] : "NULL") + " " +
items[3]
);
}
}
}
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.35%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
RyotaKondo
2016/05/17 01:09
「ループさせてなんやかんや」がプログラミングだと思うのですが、このままでは丸投げになってしまいますので、わかるところまでコードを書いてください。そもそも、「表」「入力」「出力」の定義はやりたいことごとに変わります。もしくはアルゴリズムだけでよいならばその旨を記入してください。
swordone
2016/05/17 02:05
何を言っているのかわからない上、「行増し」の法則性も全く見えてきません。これではどのようにコードを組めばいいのかすら不明瞭です。