質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

解決済

5回答

3482閲覧

二次元配列を取得・出力する順序を入れ替える冴えた方法を探しています

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

0クリップ

投稿2018/04/12 01:35

編集2018/04/12 02:15

いつもお世話になっております。

二次元配列の値を1つずつ処理する際に、for文を2つ使うことがあると思います。
例えばこんなの↓

C#

1ArrayList[,] hoge1 = new ArrayList[4,5](); 2ArrayList[,] hoge2 = new ArrayList[4,5]();//データが入っている 3 4for(int i=0;i<4;i++) //for文A 5{ 6 for(int j=0;j<5;j++) //for文B 7 { 8    //データ取得・出力部 9 hoge1[i,j].Add(hoge2[i,j][0].ToString());  10 } 11}

「for文AとBを入れ替える方法」、もしくは同じことができるアルゴリズムを探しています。

・要件
①データ取得部を丸ごとクラスにしない
②AとBを入れ替えただけのプログラムをもう1つ作らない
(データ取得部が複雑になるとこんがらがるため)
③二次元配列の行・列を入れ替えた新しい二次元配列を作らない
(データ量が多いと遅くなるので)
④データ取得部では、取得・出力ができるようにする

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

euledge

2018/04/12 01:41

行と列を入れ替えるということがやりたいことですか?そうであればその旨記載したほうが回答する側のイメージが付きやすいです
退会済みユーザー

退会済みユーザー

2018/04/12 01:48

要件③を追加しました
Zuishin

2018/04/12 05:33

そもそもこの例題が動かないので、同じ物を作れというなら最低限動くものを用意するか仕様をきちんと言葉で説明してください。ArrayList は二次元配列ではありませんし、object に Add はできませんしインデクサもありません。
guest

回答5

0

考え方の一例を

配列実体を直接扱わずビューを介してアクセスする手法です。転置などの操作は配列をコピーしたり要素を実際に入れ替えたりする必要がなくなります。

下記はインデクサー, Length, GetLengthを定義し普通の配列と同様の操作感でアクセスできるようにした例です。

C#

1// 2次元配列 2public interface Mat2<E> { 3 // インデクサー 4 E this[int i, int j] { get; set; } 5 // 全要素数 6 int Length { get; } 7 // 各次元の長さ 8 int GetLength(int rank); 9 // 転置行列のビュー 10 Mat2<E> Transpose { get; } 11} 12 13// ビューの実装 14public class Mat2View<E> : Mat2<E> { 15 public E this[int i, int j] { 16 get { return elements[i, j]; } 17 set { elements[i, j] = value; } 18 } 19 public int Length => elements.Length; 20 public int GetLength(int rank) => elements.GetLength(rank); 21 public Mat2<E> Transpose { 22 get { return new Transposed(elements); } 23 } 24 private E[,] elements; 25 public Mat2View(E[,] elements) { 26 this.elements = elements; 27 } 28 29 // 2次元配列の転置ビュー 30 class Transposed: Mat2<E> { 31 public E this[int i, int j] { 32 get { return elements[j, i]; } 33 set { elements[j, i] = value; } 34 } 35 public int Length => elements.Length; 36 public int GetLength(int rank) => elements.GetLength(1 - rank); 37 public Mat2<E> Transpose { 38 get { return new Mat2View<E>(elements); } 39 } 40 private E[,] elements; 41 internal Transposed(E[,] elements) { this.elements = elements; } 42 } 43}

用例

C#

1void foo() { 2 Mat2<int> m = new Mat2<int>(new int[2, 3]); 3 m[0, 1] = 9; 4 Mat2<int> tm = m.Transpose; 5 Console.WriteLine("m [0, 1] = " + m[0, 1]); // => 9 6 Console.WriteLine("tm[1, 0] = " + m[1, 0]); // => 9 7}

追記:上はかなり素朴な機能ですが、実際に使う場面ではコピーやLinq対応や行列演算(dot積,cross積,行列式,逆行列,etc.)など色々拡張がほしくなると思います。どこかのライブラリーにあるかも知れません。

投稿2018/04/12 04:08

編集2018/04/12 04:32
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

転置ってことで良いでしょうか?
転置行列のお話
上記でのソースコードへのリンク

画像処理では、良く行われることのようですので、探せば別なアルゴリズムもあるかもしれません。
CUDAで二次元配列の転置は高効率にできないと言ったな!あれは嘘だ!

投稿2018/04/12 02:41

編集2018/04/12 02:47
sazi

総合スコア25173

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

冴えたやり方かどうか分かりませんが下のような方法があると思います。

C#

1 2ArrayList[,] hoge1 = new ArrayList[4, 5]; 3ArrayList[,] hoge2 = new ArrayList[4, 5]; 4 5var iCount = 4; 6var jCount = 5; 7var totalCount = iCount * jCount; 8 9bool reverse = false; //ここのフラグを変えるとアクセス順序が変わる 10 11for (int n = 0; n < totalCount; n++) 12{ 13 int i = reverse ? (n % iCount) : (n / jCount); 14 int j = reverse ? (n / iCount) : (n % jCount); 15 16 //データ取得・出力部 17 hoge1[i, j].Add(hoge2[i, j][0].ToString()); 18} 19

投稿2018/04/12 04:46

MagoCat

総合スコア86

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2018/04/12 05:02

アイデアは伝わると思うのですが、実例としてはreverseによって hoge1[i,j].Add(hoge2[i,j])... hoge1[i,j].Add(hoge2[j,i])... のどちらかに切り替わるようになっていた方がよいと思います。 この例ですとi,jを入れ替えても意味があるように見えないので。 (「for文AとBを入れ替える方法」をそのまま示されたのだとは思いますが)
MagoCat

2018/04/12 05:38

> KSwordOfHasteさん この例だと意味を成さないことに関しては仰る通りです。 質問者の言う「出力」の種類によっては単なるアクセス順序の違いが意味を持ち得るのではないかと憶測しての回答になります。
KSwordOfHaste

2018/04/12 05:40

そういうことだったのですね。了解しました。
退会済みユーザー

退会済みユーザー

2018/04/13 07:04

短くて実装しやすそうですね。 こういう感じのものを探してました。 早速試してみます。
guest

0

C#

1ArrayList[,] hoge = new ArrayList[4,5](); 2 3bool change = true; 4 5for(int i=0;i<4;i++) //for文A 6{ 7 for(int j=0;j<5;j++) //for文B 8 { 9    //データ取得部 10 var a = change ? i : j; 11 var b = change ? j : i; 12 hoge[a,b].Add(a.ToString() + ":" + b.ToString());  13 } 14}

投稿2018/04/12 01:49

YamakawaJunichi

総合スコア630

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YamakawaJunichi

2018/04/12 01:51

new ArrayList[4,5] も入れ替えが必要ですね
退会済みユーザー

退会済みユーザー

2018/04/12 02:02

これだとa=5になった時エラーが出るのではないでしょうか?
YamakawaJunichi

2018/04/12 02:06

はい、そうです。 上にも書きましたがchangeに応じて行列を入れ替える必要がありますね。
退会済みユーザー

退会済みユーザー

2018/04/12 02:08

すみません。要件に書き忘れていましたが、取得だけでなく出力も考えています。 これだと出力したいデータを初期化しなければならなくなってしまいます。
guest

0

C#なんて書かないのでPHPでご了承

php

1$walk_col=true; 2$num_cols=4; 3$num_rows=5; 4 5for($i=0,$l=$num_cols*$num_rows;$i<$l;$i++){ 6 $r=$walk_col?$floor($i/$num_cols):$i%$num_cols; 7 $c=$walk_col?$i%$num_rows:floor($i/$num_rows); 8 $arr[$r][$c]; 9} 10

投稿2018/04/12 02:51

KazuhiroHatano

総合スコア7804

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問