あるテキストファイルが以下の内容で記述されているとします。
a file1
a file1
a file1
b file1
b file1
b file1
c file2
c file2
d file2
d file2
e file2
e file2
f file3
f file3
f file3
上記のように列が二つあるテキストファイルについて、
2列目のfile名が1列目のどの値とひもづいて
いるかを処理するperlプログラムを作ることを考えます。
出来上がったperlによって上記テキストファイルを処理した結果は、
file1は aとb
file2は cとdとe
file3は f
とひもづいていることが分かる ということにしたいです。
これをperlプログラムで書くとき、条件として
一行一行を読みとるとき
if ( $_ =~ /(\S+)\s+(\S+)/ ){
を使っています。
そのため$1と$2に現在行の1列目,2列目が与えられた後、
ハッシュと配列を組み合わせて考えた場合どのようにすれば
いいのでしょうか。
ご助言ご鞭撻宜しくお願い致します。
No.3ベストアンサー
- 回答日時:
> file名が一度変わり、さらに変わるときに既に出てきたfile名はエラーとする です。
同じfile名の行はひとかたまりに成っていなくてはダメということでしょうか?
であるなら、生成する部分で「直前のfile名と違い、かつ、既に出現済のfile名を取得した」場合にエラーにすれば良いでしょう。
例) ----------------------------------------------
my $previousFile = '';
while (<FILE>) {
if ($_ =~ /(\S+)\s+(\S+)/) {
if ($previousFile and $2 ne $previousFile and exists($data{$2})) {
die "$2は既に出てきたためエラーとして処理をストップしました";
}
$data{$2}{$1} = 1;
$previousFile = $2;
}
}
--------------------------------------------------
> これをループ文(whileやforeach)などで取り出す場合の記述例を御教授願います。
%result のキーでループさせてその内側で値の配列をループさせれば全要素を走査できます。file名順に並べなくても良いなら while と each の組合せでも大丈夫です。
例) ----------------------------------------------
foreach my $file (sort(keys(%result))) {
print "* $file\n";
foreach my $str (@{$result{$file}}) {
print " - $str\n";
}
}
--------------------------------------------------
単に配列が値になっているハッシュというだけの話なので、perlの制御構文やハッシュの使い方を調べれば、走査のやり方は分かるでしょう。
http://rfs.jp/sb/perl/02/06.html
http://rfs.jp/sb/perl/02/05.html
なお、ベストアンサーはどうでも良いですが、マルチポストは止めましょう。いちおう、このサイトのルールですし、質問する方も回答する方も面倒なだけでしょう。
No.2
- 回答日時:
> $data{$2} = 値 のようにキーは$2のみにして$1は値として
一度ハッシュのハッシュを作った上で、それから配列のハッシュを作るのが簡単でしょう。
例) ----------------------------------------------
my %data = ();
open(FILE, 'hoge.txt') or die "file open failed.";
while(<FILE>) {
if ( $_ =~ /(\S+)\s+(\S+)/ ) {
$data{$2}{$1} = 1;
}
}
close(FILE);
# 配列のハッシュを作る
my %result = ();
while(my ($key, $val) = each(%data)) {
$result{$key} = [sort(keys(%$val))];
}
# 生成したデータ表示してみる。
foreach my $file (sort(keys(%result))) {
print $file . " -> " . join(',', @{$result{$file}}) . "\n";
}
use Data::Dumper;
print Dumper(\%result);
--------------------------------------------------
1ループでも出来ない事はないですが、かえって面倒だと思いますよ。
> また出力はただのprintでお願いできますか。
えーと、データ表示の部分に関しては、実行した際にデータがどの様に格納されているのか確認できるように付けただけですので、コード自体の意味が分からなかったら無視して頂いても大丈夫です。
この回答への補足
root139様
御回答ありがとうございます。
すでにベストアンサーに決定することを決めています。
しかし、もう2点の課題について御教授いただければと思います。
(この課題がわからなくて答えられなくてもベストアンサーにするのでご安心を)
1点目です。
テキストファイルの続きが存在し、
g file1
g file1
g file1
のような続き行があるとします。
file1は既に出てきた値としてエラー文
「file1は既に出てきたためエラーとして処理をストップしました」
を出力させたいのです。
エラーの条件は、file列でfile1→file2→file1のように
file名が一度変わり、さらに変わるときに既に出てきたfile名
はエラーとする です。
具体的に言いますと新しい行をテキストファイルに追加する場合、
2列目は file1 file2 以外のfile名でなくてはなりません(file3は許されます)
2点目
while(my ($key, $val) = each(%data)) {
$result{$key} = [sort(keys(%$val))];
}
の%resultに格納された配列を実際に取り出したい
場合の取り出し方のバリエーションを記述お願いできますでしょうか。
$result{$key}[0]
で1列目の1個目の要素を取り出せそうに思えますが、
これをループ文(whileやforeach)などで
取り出す場合の記述例を御教授願います。
長々となってしまい申し訳ございませんが、宜しくお願い致します。
No.1
- 回答日時:
やり方はいろいろ有ると思いますが、ハッシュのハッシュを使うのが簡単だろうと思います。
例) ----------------------------------------------
my %data = ();
open(FILE, 'hoge.txt') or die "file open error!.";
while(<FILE>) {
if ( $_ =~ /(\S+)\s+(\S+)/ ) {
$data{$2}{$1} = 1;
}
}
close(FILE);
# 生成したデータ表示してみる。
foreach my $file (sort(keys(%data))) {
printf("%s -> %s\n", $file, join(',', sort(keys(%{$data{$file}}))));
}
use Data::Dumper;
print Dumper(\%data);
--------------------------------------------------
生成しているデータは、最後の Data::Dumper の出力を見てもらえば分かりますが、1列目の[a, b, c]がキーで値が1のハッシュを2列目のfile名がキーのハッシュに格納しています。
この回答への補足
ご回答ありがとうございます。
また補足ですみません。
ハッシュの値は1ではなく、
$data{$2} = 値
のようにキーは$2のみにして$1は値として
格納することを考えてますので、そういった
場合どう記述すればいいのか宜しくお願い致します。
また出力はただのprintでお願いできますか。
自分まだまだ初心者なものでして、
printfやdumperがわかりません。
普通のprintならわかります。
宜しくお願い致します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# #include <stdio.h>int main(void) { int buf[100] = 6 2022/11/01 22:45
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- その他(プログラミング・Web制作) python flask から fastapiへの移行時のエラー対処 1 2023/02/05 12:26
- UNIX・Linux Linuxの実行結果を修正したいです。 6 2022/11/22 12:57
- PHP ファイルアップロードの上限を増やす 7 2023/06/23 12:50
- Visual Basic(VBA) vbaの構文の修正相談(xmlファイルを順に開いてコピペ作業) 1 2023/04/22 01:18
- その他(プログラミング・Web制作) pythonのエラーについて 2 2022/08/17 17:17
- Visual Basic(VBA) ExcelVBAに関する質問 3 2023/02/17 10:47
- その他(プログラミング・Web制作) python 2 2022/12/23 09:06
- Visual Basic(VBA) vbaのエラー対応(実行時エラー7:メモリが不足しています) 4 2023/04/24 00:20
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
テキストファイルで提出とは?
-
ファイルをディレクトリ分配の...
-
openした後、closeしないでプロ...
-
perlのプログラミング 部分入れ...
-
Perlのエラーについてご教授く...
-
画像が表示でnull; this.src
-
perlプログラミング 空白行削除
-
Perlで特定文字列から特定文字...
-
ラズベリーパイ初心者です。 ラ...
-
アルファベットに付いて質問し...
-
#!/usr/bin/perlで書きだしたCG...
-
perlのflock関数でロックをかけ...
-
AI sisterとは、偽物の人ですか?
-
bashスクリプト
-
ファイルアイコンの左下に緑の□...
-
perlでリテラル値はメモリにど...
-
perlで2次元配列をサブルーチ...
-
Perlで時間の計算
-
perlについて
-
perlのrequireの動き方について...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
openした後、closeしないでプロ...
-
テキストファイルで提出とは?
-
INDIRECT 横に再度抽出したい
-
Perlで特定文字列から特定文字...
-
perlをバージョンアップしたら...
-
Wallpaper Engineでおすすめの...
-
arduino の割り込み処理について
-
アルファベットに付いて質問し...
-
Strawberry Perl for Windows ...
-
Perlで時間の計算
-
このファイルを開く方法で困っ...
-
TeraPadエディターの操作方法に...
-
cgiでサーバーにファイルを追加...
-
フローチャート 九九
-
LinuxにおいてのPerlのプログラ...
-
perl 初等プログラミングについて
-
Perlのエラーについてご教授く...
-
こんにちは ブラケッツでプログ...
-
bashスクリプト
-
perlプログラミング 空白行削除
おすすめ情報