• 締切済み

CSVデータの編集の際の重複チェックの方法

今、data.csv(カンマ区切り)として、左から順位、名前、性別という3項目で、10人程度のリストデータがあります。 data.csv(カンマ区切り)を編集するようにしていますが、順位は重複してはならないので、重複していたらエラーを出したいのですが。。。 ($rank,$name,$sex) = split(/\,/,$line); です。 open(IN,"$logfile") || &error("ファイルが開けません"); @lines = <IN>; close(IN); # 情報の書換え foreach $line (@lines) { ($rank,$name,$sex) = split(/\,/,$line); $line = "$in{'rank'},$name,$sex\n";} push(@new,$line); } # ファイルを更新 open(OUT,">$logfile") || &error("ファイルが開けません"); print OUT @new; close(OUT);

  • Perl
  • 回答数5
  • ありがとう数1

みんなの回答

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.5

in という名前のハッシュを使っているところからして、cgi-lib.pl を使ってますね? であれば、 > use strict; > use warnings; と >my %in; は削除してください。 しかしなんでピンポイントで、条件判定のところだけ 書き換えるということを試さないのでしょうか?

great_man2
質問者

お礼

cgi-lib.plは使っていません(^^; だめみたいです。 「しかしなんでピンポイントで、条件判定のところだけ 書き換えるということを試さないのでしょうか?」 logfileのCSVへのパスをどこに書けばいいのか分からずエラーを聞いたくらいのでレベルでして。。。 試行錯誤しながら作成していますが、「条件判定の所だけ書き換える」という事すら出来ないので・・・ あきらめますありとうございました

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.4

「教授」はしてません :-) >No such file or directory 理由がちゃんと書いてあるじゃないですか。 $logfileにログファイルの名前をいれとかないと正常動作しません。

great_man2
質問者

補足

ダメみたいです。 my $logfile = ./ranking.csv";と指定しましたが、 編集したらランキングの順位の列だけ全部空白で更新されてしまいました

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.3

まだよくわからんないところがあるんだけど、 4位以下のデータってファイルに出力する必要があるの? 1位から3位までのデータが取れればいいのでしょう? とりあえず4位以上は重複してもスルーするというだけならこんな感じ? #1の回答をベースにさせていただきましたが、 スタイルは自分好みのものに変えてますのであしからず。 use strict; use warnings; my %in; my $logfile; open my $fin, '<', $logfile or &error("ファイルが開けません ($!)"); my @lines = <$fin>; close $fin; # 情報の書換え my %seen; my @new; foreach my $line (@lines) { my ($rank, $name, $sex) = split q{,} ,$line; $line = "$in{'rank'},$name,$sex\n"; if ($seen{$rank}++ && $rank < 4) { &error("$rankは設定されています<br>現在の$rankをランク外にしてから再度設定してください。"); } push @new, $line; } # ファイルを更新 open my $fout, '>', $logfile or &error("ファイルが開けません ($!)"); print $fout @new; close $fout;

great_man2
質問者

補足

当方、全くの素人でして。。。 とりあえず、regist.cgiで、$rank, $name, $sexを入力。 edit.cgiで$rankだけ編集。 search.cgiで1位、2位、3位だけ表示としています。 ですので、edit.cgiで編集する際は全員のデータを編集するしか方法が分かりませんでした。。。 今、ご教授頂いたソースで実行すると、ファイルが開けません (No such file or directory) となってまいました。。。(^^;

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

>順位は重複してはならないので、重複していたらエラーを出したい というのに >4位以下は"9"としています(^^; という条件がついてるのがよくわかりません。 もう少し具体的なデータを例示したほうがよいように思います。 1~3位の中でだけ重複があるかどうかをチェックすればいい話なのか 順位のデータは'9' になっているけど別のフィールドを見てから 重複しているかどうかを判定しなければならないかとか。

great_man2
質問者

補足

すみません。わかりにくくて・・・ 合計20名~25名の名前と順位をCSVデータにして、 上位3位だけranking.cgiとしてCGIで表示するようにしています。 edit.cgiでCSVを編集する際には、上位3名だけ、1,2,3としていして、ランキング外のデータは全部4以上にして表示しないようにすれば完成なんですが。。。 1~3位まで重複チェックをして、ランク外は重複チェックしなくていいのです(^^;

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

「順位をキーとするハッシュ」を使うのが標準的かなぁ. 例えば %seen というハッシュに対して $seen{$rank}++; とすると, 既に $rank と同じ値を持つデータが出ていれば 0 以外の値が返りますし, そのようなデータがまだなければ 0 を返します. だから if ($seen{$rank}++) { 当該データは既出 } という形で処理できます.

great_man2
質問者

補足

ありがとうございます(^^; 下記のように明記しましたが、すみません。私の明記不足でした(^^; 上位1位、2位、3位だけデータに1,2,3と入っていて、4位以下は"9"としています(^^; 下記のように変更して実行すると、どの作業でも「設定されています」となってしまいます。 open(IN,"$logfile") || &error("ファイルが開けません"); @lines = <IN>; close(IN); # 情報の書換え foreach $line (@lines) { ($rank,$name,$sex) = split(/\,/,$line); $line = "$in{'rank'},$name,$sex\n";} if ($seen{$rank}++) { &error("$rankは設定されています<br>現在の$rankをランク外にしてから再度設定してください。");} push(@new,$line); } # ファイルを更新 open(OUT,">$logfile") || &error("ファイルが開けません"); print OUT @new; close(OUT);

関連するQ&A

  • csvデータの開始行と最終行を全体の4分の1で区切り処理をしたい

    csvデータの開始行と最終行を全体の4分の1で区切り処理をしたい csvデータの開始行と最終行を全体の4分の1で区切り処理をしたいと思ってます。 csvファイルは20万件あります。4分の1なので1~50000件となります。 今回は50001~100000件までを行いたいのですが、先日教えていただいたwhile($lines = <IN>) ですと、最初から1件ずつ最終行まで処理をしてしまいます。 (ここから) open(OUT,">$csv"); open(IN,"$data") || &error(" $data を読み込みopen出来ません"); while($lines = <IN>) { ($seq1,$categ,$password,$imail,$cont) = split("\,", $lines); $cont .= " "; $data = "$seq1,$cont,1\n"; print OUT "$data"; $data = ""; } close IN; close OUT; (ここまで) 今回は20万件ですが、毎回このデータ量は月次ごとに変わります。 while周辺をいじるような気がしていますがどのようになるのかがわからなかったので質問いたしました。 お手数かけます。 よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • CSVデータの区切りが「","」の読み取り方法

    CSVデータの区切りが「","」で区切られてます。 (ここから) "山田","埼玉県","男性" "田中","埼玉県","男性" "井上","栃木県","女性" "志村","千葉県","男性" (ここまで) 以下のような区切りで行うと思ってます。 (ここから) open(DB,"<$bunfile") || &error("Can't write $bunfile"); flock(DB, 1); @lines = <DB>; foreach $lines (@lines) { ($name,$addr,$seib) = split("\",\"", $lines); 省略; } (ここまで) この場合、先頭と最後の「"」が残ってしまいます。 どのような方法で削除出来るのかがわからず悩んでます。 「s/\"//g」を使用しようかとも思ったのですが、違う方法がないかと思い質問いたしました。 ご教授いただけますと幸いです。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • perlで容量の大きいCSVファイルを開く方法

    perlで容量の大きいCSVファイルを開く方法 ファイル容量の大きいcsvファイルから、必要な項目を抜き出して別ファイルにするプログラムを作成したいと思ってます。 csvファイルが少ない場合は動作したのですが、容量が140MBを超えたデータを読み込もうとすると、ブラウザー表示で何も変化いたしません プログラムは以下のようになってます。 ------------------------------------------------- 略 open(IN,"$inport") || &error(" $inport を読み込みopen出来ません"); flock(IN,1); @lines = <IN>; foreach $lines (@lines) { local(@val) = split("\,", $lines); print "$val[0]"; $dat .= "$val[1]\,$val[5]\n"; } open(OUT,">$dcsv"); flock(OUT,2); print OUT "$dat"; close OUT; 略 ------------------------------------------------- 件数も多いので、foreachを$lines (@lines) としないで($start .. $end)として読み込みの件数を制限して対応しようと考えてましたが、うまくいきませんでした。 ご指導いただけますと幸いです。

    • ベストアンサー
    • Perl
  • データ削除方法について

    現在以下のプログラムでデータを削除しています。 (ここから) print "Content-type: text/html\n\n"; open(IN,"<$memfile") || &error("Can't write $memfile"); flock(IN, 2); @lines = <IN>; foreach $lines (@lines) { ($seq,$name) = split("<>", $lines); if("$del" eq "$seq"){ next; }else{ $data .= $lines; } } close IN; open OUT, "> $memfile"; flock OUT, 2; print OUT $data; close OUT; print "<html>完了しました<br><a href=?mode=menu>戻る</a></body></html>"; exit; (ここまで) このプログラムでも削除出来るのですが、foreachの処理で対応するとパフォーマンスが悪いのかな? と思ってます。(ハッキリとはわかりません) 件数が多くなるとサーバーエラーになるのかな?と思ってます。 もっと効率の良い方法がありましたらと思い質問いたしました。 perlを独学で学んでいるので、見る人が見ると変なつくりだと思ってます。 以上、よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • エクセルで編集したCSVファイルを読み込むときに

    よろしくお願い致します。 エクセルで編集したCSVファイルを読み込み、HTMLとして表示するCGIがあります。 エクセルでCSVファイルを編集すると最後の項目の後にカンマ(,)が付かないのですが、 使用しているCGIでは、カンマがないと行が改行されたとみなされません。 行の最後にカンマがなくても行を改行させるには、どのようなコードを追加すればよいのでしょうか? CGIのCSVファイルの読み込みする部分のコードは以下のようになっています。 # ログファイル読み込み my $LOG_FILE = 'log.csv'; my $io = IO::File->new($LOG_FILE, 'r') or die $!; flock($io, 1); while(my $line = $io->getline) { push @ids, (split(/,/, $line))[0]; push @new_checks, (split(/,/, $line))[1]; push @dates, (split(/,/, $line))[2]; push @contents, (split(/,/, $line))[3]; push @contents2, (split(/,/, $line))[4]; push @contents3, (split(/,/, $line))[5]; push @contents4, (split(/,/, $line))[6]; push @contents5, (split(/,/, $line))[7]; push @contents6, (split(/,/, $line))[8]; } 分かりにくい説明で申し訳ありません。 補足説明も致しますので、どうぞよろしくお願い致します。

    • ベストアンサー
    • CGI
  • ACCESS VBAで、CSVにデータを吐き出したいのです

    ACCESS VBAで、CSVにデータを吐き出したいのですが、WORKのテーブルを作るのが面倒なので、変数にセットしたカンマ区切りのデータを直接CSVに吐き出したいと思っております。 TXT = .Height & "," & .Weight を Open "A:DATA.CSV" For Output As #Name へ一件ずつループで回して吐き出したいのですが、「型が一致しません」というエラーがでます。ご存知の方がいらっしゃいましたら、どいうロジックを書けば良いか教えて下さい。

  • CSVデータ「","」と「,」混在読取り出来ず

    ソート機能がうまく動作しなくなりました。 CSVが以下のようなものとなったときにソートがうまく動作しなくなってしまいました。 CSVデータの区切りが「","」と「,」の混在で区切られてます。 (ここから) データa "山田","埼玉県","男性" "田中","埼玉県","男性" "井上","栃木県","女性" "志村","千葉県","男性" (ここまで) だったり (ここから) データb 1,山田,埼玉県,男性,50,"予算2,000円",0 2,田中,埼玉県,男性,36,予算なし,0 3,井上,栃木県,女性,30,予算100円,0 4,志村,千葉県,男性,27,"予算300,000円",0 (ここまで) このようなテータの時もあります。 以前のアドバイスをもとに以下のように作成いたしました。 (ここから) while (my $line = <$ifh>) { if ($socnt == 0 ){$socnt++;next;} my $key = (split /\",\"/, $line)[$ccsv]; push @{$sorted{$key}}, $line; if (@{$sorted{$key}} == 1000) { open OUT, ">>./$key.tmp" or die "Can't open: $!"; print OUT @{$sorted{$key}}; close OUT; @{$sorted{$key}} = (); } } (ここまで) この場合だと my $key = (split /\",\"/, $line)[$ccsv]; データaはうまくいくのですが、データbがうまくソートが動作いたしません。 my $key = (split /,/, $line)[$ccsv]; ではデータbはうまくいくのですが、データaうまくソートが動作いたしません。 条件式で混在認識方法があるかと思っている(ないかもしれませんが、わたしには分かりません)ので質問いたしました。 ご教授いただけますと幸いです。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • データ件数が多くなってもエラーにならない方法

    perlで、URLからサイトが表示されるかを確認するプログラムを作成しました。 ただ現在の方法だと、チェックするデータ件数が多くなるとエラーとなってしまいます。 現在のソース (ここから) open(DB,"$memfile") || &error("Open Error : $memfile"); flock DB, 2; @lines = <DB>; close(DB); @new=(); foreach $line (@lines) { $flag=0; ($num,$url,$title) = split("<>", $line); &url_ckeck("$url"); $data = "$num<>$url<>$title\n"; $data =~ s/\n<>/<>/g; $data =~ s/\r\n<>/<>/g; $data =~ s/\r<>/<>/g; push(@new,$data); } open OUT, "> $memfile"; print OUT @new; close OUT; (ここまで) この方法だと300件を超えると「ページが表示出来ない」エラーがでてしまうので、 チェックの方法を小分けしてエラー回避できないかを考えているのですが、とのようにすれば良いのかがわからず先に進められなくなってしまいました。 プログラムも見よう見真似で作成しているのでおかしな箇所が多々あるかと思いますが、助けていただけないかと思い書き込みました。 「$line (@lines)」を「$start .. $end」として件数を小分けにしてボタンを表示させてクリックして進められるようにしてみたらとも思いましたが データがうまく更新出来ずにいます。 不明点はご指摘ください。 よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • CSVデータの同じファイルに上書きするには。

    CSV形式でデータdata.csvが書いてあります。プログラムを実行して、そのファイルの$data[4]の値が5という数字だった場合は、そこのセルだけ"解除"という文字に置き換えて(ほかに入ってる値ははそのまま)data.csvに上書きしたいのですが、どうもうまくいきません。したのように記述したのですが、どこが間違っているのかがわかりません。。どなたか教えてください。よろしくおねがいします。 #!/usr/bin/perl $file='data.csv'; open(FILE, "$file"); while(<FILE>){ @data = split(/,/, $_); } close(FILE); if($data[4] eq "5"){$data[4] = "解除";} open(OUT, ">$file"); print OUT @data; close(OUT);

  • 【初歩的質問】重複データがある時のハッシュへの代入について

    perl5.8です。すごくしようもない質問で申し訳ないのですが、次のようなファイルfile.txtの内容を、ハッシュ%hashに入れていくとします。 --- file.txtの中身 --- a,1 c,3 a,1 b,2 c,3 ----------------------- --- ソース(抜粋) ----- open(IN, "file.txt"); @data = <IN>; close(IN); %hash = (); foreach(@data){ chomp $_; @out = split(/,/, $_); $hash{$out[0]} = $out[1]; } ----------------------- 上記の結果は当然ながら、$hash{a}=1,$hash{c}=3,$hash{b}=2となるのですが、重複したデータを読み込んでハッシュに入れようとした時に、ワーニングなりエラーがなにも出なかったのがちょっと気持ち悪いです。重複したキーを読み込んだ時は、内部的には黙ってはじいてくれていると解釈してよいのでしょうか?そうだとすると、こういう書き方は、重複した行を排除するテクニックとなりえるのでしょうか?

専門家に質問してみよう