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

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

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

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

4回答

3824閲覧

Rubyで行列の(i, j)成分の値を変更するには?

manman

総合スコア233

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

1グッド

1クリップ

投稿2015/12/06 04:43

すごく初歩的なことをお聞きします。

ruby

1require 'matrix' 2 3n = 3 4a = Matrix.zero(n) 5p a[0, 1] 6a[0, 1] = 1 7p a[0, 1]

aの(0, 1)成分の値を変更しようとしたところで
エラーが出たのですが、
一般に、(i, j)成分の値を変更するには
どのように書けばよろしいのでしょうか?

DrqYuto👍を押しています

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

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

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

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

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

guest

回答4

0

ベストアンサー

RubyのMatrixは、Numericと同じで数字の一種と考えられている(行列の足し算や掛け算が用意されてある)ためか、immutable(変更不可)として設計されています。代入等で変更する方法は用意されていません。Matrixクラスにメソッドを追加して、無理矢理変更することは可能のようですが、お勧めできません。

to_aで配列にしてから再度Matrixにしてみてください。

Ruby

1require 'matrix' 2m = Matrix[[0, 1], [2, 3]] 3a = m.to_a 4a[0][1] = 100 5m = Matrix[*a] 6p m # => Matrix[[0, 100], [2, 3]]

補足ですが、行列計算を高速にして、もっと普通にアクセスしたいのであればNArrayというライブラリを使うといいかもしれません。gem install narrayでインストールできます。ただし、多倍長整数は扱えず、整数は32bitまでのようなのでご注意ください。

Ruby

1require 'narray' 2m = NMatrix[[0, 1], [2, 3]] 3m[1, 0] = 100 # 上の例とは添え字が逆になるので注意 4p m # => NMatrix.int(2,2):NMatrix.int(2,2):[ [ 0, 100 ], [ 2, 3 ] ]

投稿2015/12/06 05:40

編集2015/12/06 12:13
raccy

総合スコア21735

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

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

manman

2015/12/06 05:57

「Matrixクラスにメソッドを追加して、無理矢理変更する」ことがお勧めできない理由を教えていただけないでしょうか?
raccy

2015/12/06 06:42

manman さん ご存じの通り、Rubyはかなり自由度が高い言語で、組み込みクラスですらメソッドの追加や動作の書き換えが可能です。一部のライブラリではその仕組みを使っている場合もあります。これは他の静的な言語ではあまり見られない動的言語ならではの特徴と言えます。 しかし、自分自身がメンテナンスしていない組み込みクラスや標準ライブラリに利用者がメソッドの追加や変更をすることは推奨されていません。理由としては、下記の通りです。 1. 組み込みクラスや標準ライブラリについて内部の動作が変わる場合があります。互換性のため、表面に出ている(利用者から見える)メソッド等のAPIは基本的に変更ありません※が、内部で使われているprivateなメソッドやインスタンス変数名が大きく変更される場合があります(内部実装の手段であり、それらはAPIではないため)。Matrixの例で言うと@rowsというインスタンス変数は将来のRubyでも同じ名前で同じような実装であるという保証が一切ありません。 ※ 現在のRubyではセマンティックバージョニングを採用しており、TEENYが同じであればAPI互換は保証されています(非互換があったら、それはバグです)。 2. 将来、同名のメソッドが追加される可能性があります。追加されたメソッドが自分自身が行った実装と異なる場合、追加されたメソッドを使う他のメソッドの動作が予期せぬ動作を起こす可能性があり、わかりにくい予期せぬバグの原因になり得ます。 そして、これらは自分が書いている部分だけではなく、読み込んでいるライブラリ等のプログラム全体に関わってくるため、影響が大きすぎるという問題があります。今回は追加だけを問題にしていますが、変更までしてしまうと何が起きるかわかりません。もし、本当に拡張することで対応するならRefinementを使って効果を限定的にすることをお勧めします。 http://magazine.rubyist.net/?0041-200Special-refinement http://qiita.com/yustoris/items/77fd309178dcdd13b5cd http://blog.fenrir-inc.com/jp/2014/07/refine.html ※ 2.0では実験的、2.1から正式に使えます。 ※ 上の機能は、モンキーパッチやテストなどで既存クラスのメソッドの動作を一時的に変更するなどの特殊な場合を想定しているようです。 なお、これは第三者が作ったライブラリにも言えることですが、Gemfileを使った依存関係指定でバージョンを固定してしまえば、ある程度は避けられます(それでも混乱の元ですので、濫用はしない方がいいと思います)。
guest

0

Matrixクラスオブジェクトの一要素を書き換えるメソッドは用意されていません。
不思議ですが、ちょっと簡単にはできそうにないですね。

裏技的には、一応出来ますが。

Ruby

1require 'matrix' 2 3n = 3 4a = Matrix.zero(n) 5p a[0, 1] 6x = a.instance_variable_get(:@rows) # x はaの中身のArrayクラスオブジェクト 7x[0][1] = 1 8p a[0, 1]

投稿2015/12/06 05:55

otn

総合スコア84557

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

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

0

2次元配列の要素にアクセスするんですよね?ならば、

Ruby

1a[i][j]

(iが行番号、jが列番号)

でアクセスします。

Matrixを使ってたんですね。Matrixは使ったことがないので、適切な回答にならないかもしれませんが、ここにいささか古い情報になりますが、Matrixクラスに[]メソッドを定義して対処している例がありました。こちらを試されてみてはいかがでしょう。

投稿2015/12/06 04:57

編集2015/12/06 05:40
archiver

総合スコア1557

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

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

manman

2015/12/06 05:07

a[0, 1] = 1をa[0][1] = 1に変えましたが、エラーが出たままです。
archiver

2015/12/06 05:41

Matrixクラスを拡張して使っている例がありましたので、そちらのリンクを追記しました。
manman

2015/12/06 05:48

すいません。自己解決してしまいました。どうやら、Matrixクラスを拡張しないといけないみたいですね。
guest

0

http://www.geocities.jp/taka_owl2005/job/UNIX/tool/ruby/Matrix.html

このページを見ると、どうやら値の変更は定義されていないみたいです。
よって次のようにしてみました。

ruby

1require 'matrix' 2 3class Matrix 4 def []=(i, j, x) 5 @rows[i][j]=x 6 end 7end 8 9n = 3 10a = Matrix.zero(n) 11p a[0, 1] 12a[0, 1] = 1 13p a[0, 1] 14p a

投稿2015/12/06 05:43

編集2015/12/06 05:52
manman

総合スコア233

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問