アプリ版:「スタンプのみでお礼する」機能のリリースについて

hoge.txtの様なファイルがあって、この値を2次元の配列に格納したいのですが、簡単に実現することは可能でしょうか?

open (FILE, "hoge.txt");
foreach (<FILE>) {
# この中で、2次元の配列に格納したい
}

hoge.txt
A  1
B  2
C  3

A 回答 (3件)

可能です。

下記サンプルをお試しください。

open FILE, "hoge.txt" or die 'ファイルが開けません。';
@data = ();
while (<FILE>) {
  chomp;
  push @data, [ split /\s+/ ];
}
close FILE;

print $data[0][0];  # A
print $data[0][1];  # 1
print $data[1][0];  # B
print $data[1][1];  # 2

・ファイルの読み込みでは、foreach ではなく、while を使います。foreach でも出来なくはないのですが、効率がよくありません。

・while (<FILE>) で読み込んだデータは、特殊変数 $_ に入ります。引数を指定しない chomp や split では、この $_ が対象となります。

・[ split /\s+/ ] では、空白区切りで分割したデータのリストを初期値として、無名配列を生成しています。配列の要素が配列となるので、2次元配列として使用することが出来ます。

この回答への補足

ありがとうございます。
追加で申し訳ないですが、行数と列数を@dataから取得する方法があればおしえてください。

補足日時:2004/04/22 22:10
    • good
    • 0

> 行数と列数を@dataから取得する方法があればおしえてください。



行数は
  $rows = @data;
列数は
  $cols = @{$data[0]};
で取得できます。

ただし、「列」の部分については「無名配列」を使って動的に生成しているので、ファイル内容に不備があると、行ごとの列数が一定でなくなってしまいます。
例えば、万が一
  hoge.txt
  A  1
  B  2 7
  C  3
なんてことになっていたりすると、2次元配列の内容も同じように
  行\列 0 1 2
  0    A  1 なし(列数2)
  1    B  2  7 (列数3)
  2    C  3 なし(列数2)
のようになってしまいますので、ファイルの生成には注意が必要です。

※Perlには、C言語などのような「完全な2次元配列」を定義する方法がなく、「配列の各要素に別の配列を割り当てる」という方法で実現しているため、このような問題が起こり得ます。

この回答への補足

どうもありがとうございます。
ただ、作成しているものがどうしてもうまくいきません。ご助言いただければうれしいです。

2次元のテーブルファイルから全ての行を取得したり、指定した行を取り出すようなクラスを作りたいと思っています。new()では、指定したファイルのデータを全て2次元の配列に格納します。そして、メソッドでnew()で格納したデータを取得して処理をしたり、指定行を取り出すといった処理をしようと思います。しかし、sub側やmain側でnew()で格納したデータの値を取得することができません。

例えば

package Table;

#コンストラクタでは、指定したファイルをオープンしてデータを2次元の配列に格納しておきます。
sub new {
my($this) = shift;
my($file) = shift;
my(@data) = ();
my($rows) = 0;
my($cols) = 0;

my($fh) = new IO::File;
if ($fh->open("$file")) {
while (<$fh>) {
chomp;
push @data, [ split /\s+/ ];
}
$fh->close;
} else {
エラー処理

}
$rows = @data;
$cols = @{$data[0]};

my($tbl) = {"name" => "$file",
"data" => "@data",
"rows" => "$rows",
"cols" => "$cols"};

bless $tbl, $this;
}

#get_data()でデータを取得する
sub get_data(){
my($this) = shift;
return $this->{data}
}

sub get_rows() {
my($this)->shift;
my($indx) = shift;
  my($key) = shift;

#$this->{data}から値を検索したいが$this->{data}からうまく値を取得できない。

}

package main;

my($tbl)->new Table "File";
my(@data) = $tbl->get_data();

#@dataを使って行ごとの処理とか指定した列の値を使って処理したい。

補足日時:2004/04/23 11:47
    • good
    • 0

> ただ、作成しているものがどうしてもうまくいきません。



どう「うまくいかない」のか、がないのですが、スクリプトを解析して問題点を指摘して欲しい、ということでしょうか、、、
補足に書かれたスクリプトの問題点を挙げますので、参考にしてみてください。

・コンストラクタで IO::File を使っているが、use していない。

・get_rows の先頭と main 先頭での変数への代入式が誤っている。それぞれ
  my($this)->shift;
     ↓
  my($this) = shift;

  my($tbl)->new Table "File";
     ↓
  my($tbl) = new Table "File";
ちなみに、get_rows のように引数が複数ある関数では、
  my ($this,$index,$key) = @_;
と書くことができます。

・オブジェクトの生成で、data の持ち方がおかしい(これが一番問題)。
  "data" => "@data",
では、$tbl->{data} の内容は「リファレンス値を列挙した文字列」になってしまいます。ここでは配列データを持たせるべきなので
  "data" => \@data,
とします。ダブルクォートは付けてはいけません。

こうすると、$tbl->get_data の戻値もリファレンスになるので、受け取る側は
  my $data = $tbl->get_data;
のようにし、各要素へのアクセスは、
  $data->[$row][$col]
のようにします。

まずはリファレンスについての理解を深めることを勧めます。

リファレンスについてのドキュメント
 http://www.kt.rim.or.jp/~kbk/perl5.005/perlref.h …

2次元配列の扱いに関するドキュメント
 http://www.kt.rim.or.jp/~kbk/perl5.005/perllol.h …

参考URL:http://www.kt.rim.or.jp/~kbk/perl5.005/perlref.html,http://www.kt.rim.or.jp/~kbk/perl5.005/perllol.h …
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!