C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: 関数をひとつにする方法を教えてください。


(過去ログ 132 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■78063 / inTopicNo.1)  関数をひとつにする方法を教えてください。
  
□投稿者/ ミルク (18回)-(2015/12/11(Fri) 10:21:20)

分類:[.NET 全般] 

以下のような配列があるとします

string[,] s23 = new string[2, 3] { { "A", "1", "a" }, { "B", "2", "b" } };
string[,,] s234 = new string[2, 3, 4] {
 {{ "A1", "A2", "A3", "A4" }, { "B1", "B2", "B3", "B4" }, { "C1", "C2", "C3", "C4" }},
 {{ "D1", "D2", "D3", "D4" }, { "E1", "E2", "E3", "E4" }, { "F1", "F2", "F3", "F4" }},
};

以下の文字列を取得する関数をひとつにまとめるにはどうすればよいのでしょうか?
string[,] s23 ⇒ "A, 1, B, 2, C, 3",
string[,,] s234 ⇒ "A1, A2, A3, A4, B1, B2, B3, B4, C1, C2, ・・・・ E3, E4, R1, F2, F3, F4"


やはり、以下のようにそれぞれ必要な次元数別に作るしかないのでしょうか?

private string Get2(dynamic Array)
{
 string str = "";
 for(int inum1 = 0; inum1 < Array.GetLength(0); inum1++)
 {
  for(int inum2 = 0; inum2 < Array.GetLength(1); inum2++)
  {
   str += ((str == "") ? "" : ", ") + Array[inum1, inum2];
  }
 }
 return (str);
}

private string Get3(dynamic Array)
{
 string str = "";
 for(int inum1 = 0; inum1 < Array.GetLength(0); inum1++)
 {
  for(int inum2 = 0; inum2 < Array.GetLength(1); inum2++)
  {
   for(int inum3 = 0; inum3 < Array.GetLength(2); inum3++)
   {
    str += ((str == "") ? "" : ", ") + Array[inum1, inum2, inum3];
   }
  }
 }
 return (str);
}
引用返信 編集キー/
■78064 / inTopicNo.2)  Re[1]: 関数をひとつにする方法を教えてください。
□投稿者/ Hongliang (382回)-(2015/12/11(Fri) 11:05:50)
こんなのとか
var combined = String.Join(", ", array.Cast<string>());

引用返信 編集キー/
■78067 / inTopicNo.3)  Re[2]: 関数をひとつにする方法を教えてください。
□投稿者/ ミルク (19回)-(2015/12/11(Fri) 13:41:52)
2015/12/11(Fri) 13:50:13 編集(投稿者)
2015/12/11(Fri) 13:48:55 編集(投稿者)

No78064 (Hongliang さん) に返信
> var combined = String.Join(", ", array.Cast<string>());

ありがとうございます。

いろいろと試してみてて新たな質問なのですが

string[] s2 = new string[2] { "A", "B" };
string[,] s23 = new string[2, 3] { { "A", "1", "a" }, { "B", "2", "b" } };

このとき
List<string> slst = new List<string>(s2);
これはできて
List<string> slst = new List<string>(s23);
これができない

最終的に string.Join(",", slst) で同じものを得ようとしたのですけど。
List<string> だとできないのでしょうか?

ちなみに s23.Cast<List<string>>()
これもできなかったです。

間抜けっぽいんですけど一度 ',' をつけてまた分割すればできましたけど。

List<string> slist = new List<string>( (String.Join(", ", s23.Cast<string>())).Split(',') );

これが普通なのでしょうか?




引用返信 編集キー/
■78068 / inTopicNo.4)  Re[3]: 関数をひとつにする方法を教えてください。
□投稿者/ Hongliang (383回)-(2015/12/11(Fri) 14:02:03)
> このとき
> List<string> slst = new List<string>(s2);
> これはできて
> List<string> slst = new List<string>(s23);
> これができない

配列は、IList(とIListが持っているIEnumerable)は派生元のArrayが実装しているので必ず実装していますが、IList<T>(とIList<T>が持っているIEnumerable<T>)は1次元配列にしか実装されません。
List<T>のコンストラクタには
new List(IEnumerable<T>)
があるので、IList<T>(が持っているIEnumerable<T>)を実装している1次元配列は渡せますが、2次元以上の配列はIList<T>もIEnumerable<T>も実装していないので渡せません。

Enumerable.Cast<T>拡張メソッドは、IEnumerableをIEnumerable<T>に変換するメソッドです。
(もちろん、IEnumerableがT型以外の要素まで返すようなコレクションの場合は実行時例外になりますが)
2次元以上の配列でも、IList/IEnumerableは持っているので、Cast拡張メソッドを使うことでstring[,]をIEnumerable<string>として扱えるようになります。
もちろん、List<T>のコンストラクタにも渡せます。
var list = new List<string>(array.Cast<string>());
引用返信 編集キー/
■78069 / inTopicNo.5)  Re[3]: 関数をひとつにする方法を教えてください。
□投稿者/ 魔界の仮面弁士 (599回)-(2015/12/11(Fri) 14:18:39)
No78067 (ミルク さん) に返信
> List<string> slst = new List<string>(s23);
> これができない

そういう場合には、
 List<string> slst2 = new List<string>(s23.Cast<string>());
にすれば OK かと。


そもそも List<string> コンストラクタのオーバーロードは、
 (1) 引数無し
 (2) 「int 初期要素数」
 (3) 「IEnumerable<string> コピー元コレクション」
の 3 種類があります。今回利用するのは (3) ですね。



1 次元配列である s2 は、インターフェイスとして
  ICloneable
  IList
  ICollection
  IEnumerable
  IStructuralComparable
  IStructuralEquatable
  IList<string>
  ICollection<string>
 ★IEnumerable<string>
  IReadOnlyList<string>
  IReadOnlyCollection<string>
を実装しているため List<string> コンストラクタに渡せますが、
多次元配列である s23 の場合には、
  ICloneable
  IList
  ICollection
  IEnumerable
  IStructuralComparable
  IStructuralEquatable
しか実装されていないため、List<string> 化できないというわけです。


なお、s23.Cast<string>() の場合は、下記のインターフェイスが含まれます。
  IEnumerable<string>
  IEnumerable
 ★IEnumerator<string>
  IDisposable
  IEnumerator
引用返信 編集キー/
■78070 / inTopicNo.6)  Re[4]: 関数をひとつにする方法を教えてください。
□投稿者/ ミルク (20回)-(2015/12/11(Fri) 14:47:46)
No78068 (Hongliang さん) に返信

> Enumerable.Cast<T>拡張メソッドは、IEnumerableをIEnumerable<T>に変換するメソッドです。
> (もちろん、IEnumerableがT型以外の要素まで返すようなコレクションの場合は実行時例外になりますが)
> 2次元以上の配列でも、IList/IEnumerableは持っているので、Cast拡張メソッドを使うことでstring[,]をIEnumerable<string>として扱えるようになります。
> もちろん、List<T>のコンストラクタにも渡せます。
> var list = new List<string>(array.Cast<string>());

ちなみに、逆(s234array に s234 を入れる)もできるのでしょうか?
string s234 = "A1,A2,A3,A4,B1,B2,B3,B4,C1,C2,C3,C4,D1,D2,D3,D4,E1,E2,E3,E4,F1,F2,F3,F4";
string[, ,] s234array = new string[2, 3, 4];


引用返信 編集キー/
■78076 / inTopicNo.7)  Re[5]: 関数をひとつにする方法を教えてください。
□投稿者/ Hongliang (384回)-(2015/12/11(Fri) 17:16:18)
> ちなみに、逆(s234array に s234 を入れる)もできるのでしょうか?

できるかできないかで言えばもちろんできます。
1行で書けるかと言えばNOです。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -