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

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

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

Re[7]: Listと配列のコピー


(過去ログ 132 を表示中)

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

■77879 / inTopicNo.1)  Listと配列のコピー
  
□投稿者/ KH (16回)-(2015/11/27(Fri) 17:24:26)

分類:[C#] 

まずはこちらのページ
http://kan-kikuchi.hatenablog.com/entry/C%23Tip3
に記載された内容を元にディープコピーしようと思ったのですが

//配列→List
string[] stringArray = new string[] {"test1", "test2"};

List<string> stringList = new List<string>();
stringList.AddRange(stringArray);

//List→配列
List<string> stringList = new List<string>(){"test1", "test2"};

string[] stringArray = stringList.ToArray();
/////////////////////////////////////////////////////////////////////////
上記を参照にこのようなコードを書いてみました。

string[] stringArray1 = new string[] { "11", "12" };
string[] stringArray2 = new string[] { "21", "22" };
List<string> stringList = new List<string>();

private void button1_Click(object sender, EventArgs e)
{
stringList.AddRange(stringArray1);
stringList.AddRange(stringArray2);
string a = "";
for (int x = 0; x < stringList.Count; x++)
{
for (int y = 0; y < stringList[x].Length; y++)
{
a += stringList[x][y] + ",";
}
a += "\r\n";
}

textBox1.Text = a;
}
///////////////////////////////////////////////////////////////////////
すると結果は
1,1,
1,2,
2,1,
2,2,
こうなってしまいました。
AddRangeの時点で
{ "11", "12" }→{ "1", "1" },{ "1", "2" }
こうなってしまっているようです。
11,12,
21,22
と表示させるにはどうしたらよいのでしょうか?
また、Listの末尾に追加するとき
ディープコピーする方法を配列→List、List→配列ともに
ご紹介いただけましたら嬉しいです。
引用返信 編集キー/
■77880 / inTopicNo.2)  Re[1]: Listと配列のコピー
□投稿者/ Hongliang (376回)-(2015/11/27(Fri) 17:52:48)
ん?
List<string>は1次元のstringリストですよ?
AddRangeを完了した時点で、stringListは
{ "11", "12", "21", "22" }
という要素を持つことになります。
外側のforで、stringListのCountは4なので4行出力されることになり、
内側のforで、
1行目なら"11"の0番目である'1', "11"の1番目である'1'が、
3行目なら"21"の0番目である'2', "11"の1番目である'1'が、
順番に出力されています。

2次元で持ちたいのなら、List<List<string>>というリストが必要ですが…。
引用返信 編集キー/
■77882 / inTopicNo.3)  Re[2]: Listと配列のコピー
□投稿者/ KH (17回)-(2015/11/27(Fri) 18:14:02)
Hongliangさん

ご指摘ありがとうございます。誠に迂闊でした。
わたしが本当にやりたかったことは
List<int[,]> intlist = new List<int[,]>();
int[,] intarray;
この二つの配列→List、List→配列のディープコピーをどうやったらできるのかということです。
申し訳ないです。
引用返信 編集キー/
■77883 / inTopicNo.4)  Re[3]: Listと配列のコピー
□投稿者/ 魔界の仮面弁士 (573回)-(2015/11/27(Fri) 18:31:18)
No77882 (KH さん) に返信
> わたしが本当にやりたかったことは
> List<int[,]> intlist = new List<int[,]>();
> int[,] intarray;
> この二つの配列→List、List→配列のディープコピーをどうやったらできるのかということです。

二つの配列というのが、どれとどれを指しているのか読み取れませんでした。

intlist と intarray の 2 つから、新たな List を作るという事でしょうか?
それとも、intlist の内容を基にして、intarray を作るという事でしょうか?


たとえば 変数 intlist の内容が
 List<int[,]> intlist = new List<int[,]>();
 intlist.Add(new int[,] { { 111, 112 }, { 121, 122 }, { 131, 132 } });
 intlist.Add(new int[,] { { 211, 212 }, { 221, 222 }, { 231, 232 } });
 intlist.Add(new int[,] { { 311, 312 }, { 321, 322 }, { 331, 332 } });
だったと仮定して、intarray がどうあるべきなのか、
具体例を示して頂けないでしょうか。
引用返信 編集キー/
■77885 / inTopicNo.5)  Re[4]: Listと配列のコピー
□投稿者/ KH (18回)-(2015/11/27(Fri) 19:11:07)
魔界の仮面弁士さんへ
書き方が下手だったみたいです。
この二つの、配列→List、List→配列のディープコピーをどうやったらできるのかということです。
     ↑ ここに点を打っとけばよかったです。

仮定のintarryは
例えばinllistの再末尾のアドレスではなく値をコピーして
{ 311, 312 }, { 321, 322 }, { 331, 332 } }
になり,intlistの値が変わってもintarryの値は変わらないようなディープコピーの仕方を教わりたかったのです。

引用返信 編集キー/
■77886 / inTopicNo.6)  Re[5]: Listと配列のコピー
□投稿者/ 魔界の仮面弁士 (574回)-(2015/11/27(Fri) 19:18:33)
No77885 (KH さん) に返信
> intlistの値が変わってもintarryの値は変わらないようなディープコピーの仕方を教わりたかったのです。


こういうことで良いのかな。

List<int[,]> intlist = new List<int[,]>();

int[,] intarray = { { 11, 12 }, { 21, 22 }, { 31, 32 } };

intlist.Add((int[,])intarray.Clone()); // 複製を登録
intlist.Add((int[,])intarray); // 同じ参照を登録

Console.WriteLine(intarray[2, 1]); // 32
Console.WriteLine(intlist[0][2, 1]); // 32
Console.WriteLine(intlist[1][2, 1]); // 32

intarray[2, 1] = 999; // 32 から 999 に変更

Console.WriteLine(intarray[2, 1]); // 変更したので 999
Console.WriteLine(intlist[0][2, 1]); // 複製には影響が無いので 32
Console.WriteLine(intlist[1][2, 1]); // 元の配列への参照なので 999

引用返信 編集キー/
■77887 / inTopicNo.7)  Re[6]: Listと配列のコピー
□投稿者/ 魔界の仮面弁士 (575回)-(2015/11/27(Fri) 19:34:51)
No77886 (魔界の仮面弁士) に追記
> intlist.Add((int[,])intarray.Clone()); // 複製を登録
> intlist.Add((int[,])intarray); // 同じ参照を登録

上記では、対比のために共にキャストしていますが、
実際には後者のキャストには意味が無く、
 intlist.Add((int[,])intarray.Clone());
 intlist.Add(intarray);
と同じ意味です。


また、int[,] のような『値型の配列』ではなく、
『参照型の配列』であった場合には、配列の要素に対しても
複製を作成する必要がありますね。
http://smdn.jp/programming/netfx/cloning/
引用返信 編集キー/
■77919 / inTopicNo.8)  Re[7]: Listと配列のコピー
□投稿者/ KH (19回)-(2015/12/01(Tue) 16:43:27)
時間がたってしまいましたすいません。

配列→List
intlist.Add((int[,])intarray.Clone());
List→配列
intarray = (int[,])intlist[intlist.Count - 1].Clone();

としてコピーすれば簡潔に一行でディープコピーすることができました。
ありがとうございます。

これに関して計測をしてみました。
以下のようなコードを書いて
    int[,] intarray = new int[4, 4];
List<int[,]> intlist = new List<int[,]>();
int kaisi;
private void button2_Click(object sender, EventArgs e)
{
kaisi = Environment.TickCount;
Thread th = new Thread(hoge);
th.Start();
}
private delegate void dlmain();
private void hoge()
{

for (int x = 0; x < 100000; x++)
{
intlist.Add(new int[4, 4]
{ { x + 1, x - 1, x + 1, x - 1}
,{ x + 2, x - 2, x + 2, x - 2}
,{ x + 3, x - 3 ,x + 3, x - 3}
,{ x + 4, x - 4 ,x + 4, x - 4}});
        //////////////////////////////////////////////////////////////////////////
/*for (int j = 0; j < 4; j++)
{
for (int k = 0; k < 4; k++)
{
intarray[j, k] = intlist[intlist.Count - 1][j, k];
}
}*/
intarray= (int[,])intlist[intlist.Count - 1].Clone();
//////////////////////////////////////////////////////////////////////////
string s = "";
for (int b = 0; b < 4; b++)
{
for (int c = 0; c < 4; c++)
{
s += intarray[b, c] + ",";
}
s += "\r\n";
}
Invoke(new dlmain(delegate
{
textBox1.Text = s;
label1.Text = TimeSpan.FromMilliseconds(Environment.TickCount - kaisi).ToString();
Refresh();
}));
}
}

1、地道に1個づつ代入する
for (int j = 0; j < 4; j++)
{
for (int k = 0; k < 4; k++)
{
intarray[j, k] = intlist[intlist.Count - 1][j, k];
}
}
2、簡潔に一行でディーコピー
intarray = (int[,])intlist[intlist.Count - 1].Clone();

10万回ディープコピーをした計測結果です。
これをした所
1、2分25秒891
2、3分28秒844
何と一個づつループして代入する方が速かったのです。

どうも教えて頂いてありがとうございました。

解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -