（vb.net）カンマ区切りで複数の要素を持つ文字列に関して（配列、etc）

# はじめに
はじめてこういったメモを残します。初心者です。
下記シチュエーションに対してすごくどんくさい方法のコードを書いていたのですが、良い方法を教えてもらったのでちゃんと知っておきたいな～と思い、めもめも。

vb.net以外の言語でもできることかも。私以外の誰かにとっても役に立てば幸いです。

###シチュエーション
Web.configに、

- アイドル名コード
- アイドル名
- グッズコード
- グッズJANコード

をセットで登録。これを、vbファイル側で配列に入れ使用する。
ただし、下記のような注意点がある。

* グッズコードとグッズJANコードは同じ数だけあり、紐づいている（グッズコード：グッズJANコード = 1:1）
* ~~アイドル名コード：グッズコード = 1:1。~~⇒【仕様変更】一部アイドルに関しては紐づくグッズコード・グッズJANコードが複数ある（アイドル名コード：グッズコード = 1:n）

#今まで書いていたプログラム
###Web.config例

```vb:Web.config
<!-- value = アイドルコード、アイドル名、グッズコード①、グッズJANコード①、グッズコード②、グッズJANコード②、… -->
<add key="80sIDOL_akina01" value="akina01,中森明菜,akina_photo01,aaaa01"/>
<add key="80sIDOL_seiko01" value="seiko01,松田聖子,seiko_photo01,ssss01,seiko_photo02,ssss02"/>
```

（上記、Web.configなので本当なら言語はasp.netかと思うのですが上手く設定できなんだ…一先ずvbとしてしまいましたすみません。後で気づいたら直します）

シチュエーションとしては「とあるアイドルショップに、明菜ちゃんのグッズ（生写真）が1種、聖子ちゃんのグッズ（生写真）が2種ある」状態なんだなと思ってください。Valueにカンマ区切りで要素（データ）を複数、持たせています。
明菜ちゃんのグッズが1種に対し、聖子ちゃんのグッズが2種（複数）あることが、本メモのポイントです。

###vb.net（vbファイル）例…For文を用いるパターン

```vb:Set_IdolDoods.vb
'Splitメソッドを用いて、文字列を分割して配列にする
Dim IDOL_Akina01 As String() = (ConfigurationManager.AppSettings("80sIDOL_akina01")).Split(",")
Dim IDOL_Seiko01 As String() = (ConfigurationManager.AppSettings("80sIDOL_seiko01")).Split(",")

'聖子グッズコードのセットを生成
Dim GoodsCD_Seiko As String = ""
For i As Integer = 2 To IDOL_Seiko01.Length - 1 Step 2
	'配列IDOL_Seiko01(2)が聖子グッズコードのスタート、そこから一つ飛ばし(Step 2)でグッズコードが続く
	GoodsCD_Seiko = GoodsCD_Seiko + IDOL_Seiko01(i) + ","
Next
If GoodsCD_Seiko.Length <> 0 Then
	'グッズコードが挿入されているとき、最後のカンマを取る
	'※この方法だと、グッズコードが1件しか挿入されていない場合はコードの右端1文字が削られる。再度仕様変更が起きた際に危険
	GoodsCD_Seiko.Remove(GoodsCD_Seiko.Length - 1, 1)
End If
'聖子グッズJANコードのセットを生成
Dim GoodsJAN_Seiko As String = ""
For i As Integer = 3 To IDOL_Seiko01.Length - 1 Step 2
	'配列IDOL_Seiko01(3)が聖子グッズJANコードのスタート、そこから一つ飛ばし(Step 2)でグッズJANコードが続く
	GoodsJAN_Seiko = GoodsJAN_Seiko + IDOL_Seiko01(i) + ","
Next
If GoodsJAN_Seiko.Length <> 0 Then
	'グッズJANコードが挿入されているとき、最後のカンマを取る
	'※この方法だと、グッズJANコードが1件しか挿入されていない場合はコードの右端1文字が削られる。再度仕様変更が起きた際に危険
	GoodsJAN_Seiko.Remove(GoodsJAN_Seiko.Length - 1, 1)
End If

If [中森明菜のデータが欲しい] Then
	Idol_CD = IDOL_Akina01(0)
	Idol_Name = IDOL_Akina01(1)
	Goods_CD = IDOL_Akina01(2)
	Coods_JANCD = IDOL_Akina01(3)
End If
If [松田聖子のデータが欲しい] Then
	Idol_CD = IDOL_Seiko01(0)
	Idol_Name = IDOL_Seiko01(1)
	Goods_CD = GoodsCD_Seiko	'生成したグッズコードセットを使用
	Coods_JANCD = GoodsJAN_Seiko	'生成したグッズJANコードセットを使用
End If
```

If文の条件部をさぼっていますが、ここで言いたいのはそこではなく、

- For文を使用してグッズコード・グッズJANコードのセットを作成していた
- コードのセットを作る際に、セットの最後に付いたカンマの取り方が危険な方法である

というところ。For文部分、複雑ではないとはいえ、Step等も用いていて簡潔ではないのは確かです。また、コメントにも書きましたが…仕様変更が発生し聖子ちゃんグッズが1種になったとき、カンマを取り除くIf文が生きていたらコードが削られてしまうので大変危ない。

ということで、改善していきましょう。

#今回知った改善案
###Web.config例

```vb:Web.config
<!-- value = アイドルコード、アイドル名、グッズコード、グッズJANコード -->
<add key="80sIDOL_akina01" value="akina01,中森明菜,akina_photo01,aaaa01"/>
<add key="80sIDOL_seiko01" value="seiko01,松田聖子,seiko_photo01?seiko_photo02,ssss01?ssss02"/>
```

既に、先ほどのまでの書き方と違いが見られます。「グッズコードを、"?"で繋いでひとまとめに」しています。これをどう使用するかは下記の通り。

###vb.net（vbファイル）例…Replaceメソッドを用いるパターン
```vb:Set_IdolDoods.vb
'Splitメソッドを用いて、文字列を分割して配列にする
Dim IDOL_Akina01 As String() = (ConfigurationManager.AppSettings("80sIDOL_akina01")).Split(",")
Dim IDOL_Seiko01 As String() = (ConfigurationManager.AppSettings("80sIDOL_seiko01")).Split(",")

'聖子グッズコードのセットを生成
Dim GoodsCD_Seiko As String = ""
Dim GoodsCD_Seiko = Sisha_Sohonten(2).Replace("?", ",")		'Replaceメソッドで"?"を","に変換
'聖子グッズJANコードのセットを生成
Dim GoodsJAN_Seiko As String = ""
Dim GoodsJAN_Seiko = Sisha_Sohonten(3).Replace("?", ",")	'Replaceメソッドで"?"を","に変換

If [中森明菜のデータが欲しい] Then
	Idol_CD = IDOL_Akina01(0)
	Idol_Name = IDOL_Akina01(1)
	Goods_CD = IDOL_Akina01(2)
	Coods_JANCD = IDOL_Akina01(3)
End If
If [聖子のデータが欲しい] Then
	Idol_CD = IDOL_Seiko01(0)
	Idol_Name = IDOL_Seiko01(1)
	Goods_CD = GoodsCD_Seiko
	Coods_JANCD = GoodsJAN_Seiko
End If
```

聖子グッズのコードのセットを生成している点は前と変わりないですが、生成の方法に、改善版Web.configで見られた"?"が活きています。Replaceメソッドを用いて"?"を","に変換することで「seiko_photo01?seiko_photo02」という塊が「seiko_photo01,seiko_photo02」となるわけですね。改善前と比べ、グッと簡単になりました。

####改善案のメリット
- コードが簡潔（単純に行数が減る、For文のStep間違い等つまらないミスを減らせる）
- 「グッズコードとグッズJANコードは同じ数だけある」という法則が成り立たなくなっても、コードの改修をしなくて済む
- configの記述に関しても、どこがグッズコードなのかがわかりやすい（グッズコード、グッズJANコードでひとつの塊になっているため）

思いつくメリットを超ざっくりと上げてみました。
ちゃんと見ていないので上記には上げませんでしたが、計算速度とかも速くなっていたりするかもです。

####改善案のデメリット
- コードに「?」が含まれる場合は別の文字で区切る必要がある

「コードに含まれる可能性のある文字を用いて区切ってしまうと、Replaceメソッドで置換するときにコードが書き換わってしまうよね」という話。コードが作成されるときのルールがきちんと定められてれば問題はないので大きなデメリットではなさそう。
他にもあるのだろうか…。

# おわりに
はじめてメモ書きを公開してみましたが、コードも普通の文章も、上手に書くには経験が必要ですね…頑張ります。
ちなみに、私は明菜ちゃん派です。

###以下、自分用メモ

- 改善前コード…セット最後のカンマを除くIF文：もっと簡単な方法でカンマを取り除けたのでは？
- 改善前と改善後…計算速度の違いをちゃんと測ってみたい。
- 改善前と改善後…最後、IF文を使用して[中森明菜のデータが欲しい][松田聖子のデータが欲しい]チェックをしていたが、Select CaseではなくIF文を使用したのは何故だったか…振り返りたい。
- 記事（メモ）の書き方…状況説明が難しかった。良くしていきたい。
- 記事（メモ）の書き方…タイトルの付け方が難しかった。というかタイトルと内容が一致していない、けど簡潔なタイトルが思い浮かばない。良くしていきたい。