• ベストアンサー
  • 困ってます

シュワルツ変換の不具合

  • 質問No.2207890
  • 閲覧数136
  • ありがとう数3
  • 気になる数0
  • 回答数4
  • コメント数0

お礼率 21% (18/84)

シュワルツ変換の不具合で困っています。

http://oshiete1.goo.ne.jp/kotaeru.php3?q=1959574
http://oshiete1.goo.ne.jp/kotaeru.php3?q=1882190
で質問したものです。

#!/usr/local/bin/perl
print "Content-type: text/html\n\n";
&hoge;
sub hoge{
open(o,"hoge.txt");
@all = <o>;
close(o);
for (@all){
($sentence,$filename) = split(/,/,$_);
$score++;
push @hoge, ($score,$_,"<br>\n");
}
@hoge = map {$_->[0]} sort {$b->[1] <=> $a->[1]} map {[$_, split /,/]}@hoge;
print @hoge;
}

というcgiを作成し、実行してみたのですが望んだ処理が出来ません。
hoge.txtは

,123,abc.txt
,456,def.txt
,789,ghi.txt
,123,jkl.txt
,456,mno.txt
,789,pqr.txt

という内容です。

cgiを実行すると
6 5 4 3 2 1 ,789,pqr.txt
,456,mno.txt
,123,jkl.txt
,789,ghi.txt
,456,def.txt
,123,abc.txt
となってしまいスコアが先頭に集まってしまいます。
シュワルツ変換の行を削除すると
6,789,pqr.txt
5,456,mno.txt
4,123,jkl.txt
3,789,ghi.txt
2,456,def.txt
1,123,abc.txt

こうなるのですが、これをシュワルツ変換を用いて
1,123,abc.txt
2,456,def.txt
3,789,ghi.txt
4,123,jkl.txt
5,456,mno.txt
6,789,pqr.txt

と出力させたいのです。
どこをどのように変えればよいでしょうか。
宜しくお願いします。

質問者が選んだベストアンサー

  • 回答No.1
  • ベストアンサー

ベストアンサー率 62% (800/1280)

チェックすべき点が2つあります。
push @hoge ... の結果、@hogeにはどういうデータが入っていますか?
期待通りのデータ構造では入っていないはずです。
最初のmapを適用した結果はどういうデータ構造になっているか把握していますか?

こういうときは、標準モジュールの Data::Dumper を使って、データ構造をチェックしましょう。
また、オープンするファイルハンドルに小文字のbarewrodを使うのは習慣として勧められません。大文字を使うか、例に挙げたようにmy変数を使いましょう。
ただし古いバージョンのPerlだと使えませんが。

それと、読み込んだデータを2度splitしていますが、一度目のsplitの
結果である $sentenceと$filenameを使っていないようですがなぜでしょう?

#!/usr/local/bin/perl
use strict;
use warnings;

print "Content-type: text/html\n\n";

&hoge;

sub hoge{
  my @all = <DATA>;
  my @hoge;
  my $score;

  for (@all){
    my $sentence;
    my $filename;
    ($sentence, $filename) = split /,/, $_;
    $score++;
    #push @hoge, ($score, $_, "<br>\n");
    push @hoge, [$score, $_, "<br>\n"];
  }
  #print join ':::', @hoge;
  #print "#####\n";

  #use Data::Dumper;
  #my @mapped = map {[$_, split /,/, $_->[1]] } @hoge;
  #print Dumper(@mapped);
  # @hoge = map {$_->[0]} sort {$b->[1] <=> $a->[1]} map {[$_, split /,/]}@hoge;

  my @sorted = map { $_->[0] }
        sort { $b->[2] <=> $a->[2]}
        map {[$_, split /,/, $_->[1]] } @hoge;

  #print Dumper(@sorted);

  foreach my $item (@sorted) {
    print join(':', @{$item}), "\n";
  }
}
__END__
,123,abc.txt
,456,def.txt
,789,ghi.txt
,123,jkl.txt
,456,mno.txt
,789,pqr.txt
お礼コメント
gonntetu

お礼率 21% (18/84)

データ構造までは把握していませんでした。
習慣やDumper等も含めて、もう一度丁寧にPerlを学ぼうと思います。
splitはこのcgiに今後コードを追加しようと思っているのですが、消し忘れてしまったものです。
ご回答ありがとうございました。
投稿日時:2006/06/11 12:59

その他の回答 (全3件)

  • 回答No.4

ベストアンサー率 62% (800/1280)

補足です。
pushした順に番号をつけて出力すればいいのなら、
pushではなくunshiftで配列に追加するか、
foreachでとりだすときにreverseしてやれば良くて、
わざわざ重いソートなんてやる必要ないのでは。
補足コメント
gonntetu

お礼率 21% (18/84)

おっしゃる通りなのですがこのあと色々コードを追加して処理するので
質問に シュワルツ変換を用いて
と付け加えさせていただきました。
投稿日時:2006/06/11 12:44
  • 回答No.3

ベストアンサー率 52% (9/17)

興味があったもので…
私も #2 の方が回答されてるように @hoge の中身が怪しいかと…

push @hoge, ($score,$_,"<br>\n");

これでは
$hoge[0] = "1";
$hoge[1] = ",123,abc.txt\n";
$hoge[2] = "<br>\n";
$hoge[3] = "2";
$hoge[4] = ",456,def.txt\n";
$hoge[5] = "<br>\n";

という風に値が入ってしまいますが…
下記のような形を望んでいるのでは?

$hoge[0] = "1,123,abc.txt\n,<br>\n";
$hoge[1] = "2,456,def.txt\n,<br>\n";

こうした上で配列 @hoge の第一項($score)でソートすれば

@hoge = map {$_->[0]} sort {$a->[1] <=> $b->[1]} map {[$_, split /,/]}@hoge;

これで期待通りの結果が得られるのでは…
お礼コメント
gonntetu

お礼率 21% (18/84)

てっきり
push @hoge, ($score,$_,"<br>\n");
とすれば
$hoge[0] = "1,123,abc.txt\n,<br>\n";
$hoge[1] = "2,456,def.txt\n,<br>\n";
となるものだと思っていました。
これじゃあ上手くできませんよね。
ご回答ありがとうございました。
投稿日時:2006/06/11 13:04
  • 回答No.2

ベストアンサー率 50% (3003/5914)

>push @hoge, ($score,$_,"<br>\n");
が悪いと思います。
>push @hoge, "$score$_<br>\n";
とでもすればいいんじゃないかと思います。
あと、
for (@all){
の後に、
chomp;
を入れた方がいいかも・
お礼コメント
gonntetu

お礼率 21% (18/84)

カッコだけでこんなに処理が変わってしまうとは思っていませんでした。
基本から復習したいと思います。
ご回答ありがとうございました。
投稿日時:2006/06/11 13:01
結果を報告する
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。
AIエージェント「あい」

こんにちは。AIエージェントの「あい」です。
あなたの悩みに、OKWAVE 3,600万件のQ&Aを分析して最適な回答をご提案します。

関連するQ&A

その他の関連するQ&Aをキーワードで探す

ピックアップ

ページ先頭へ