予約カレンダーを作っています。
ユーザーは不特定の日を予約できます。
CSVファイル
2,1029,2007/1/15,C,
3,1029,2007/1/15,B,checked
4,1029,2007/1/10,D,
5,1029,2007/1/9,C,checked
6,1029,2007/1/16,D,
8,1023,2007/1/17,D
9,1023,2007/1/24,D
10,1023,2007/1/24,C
11,1023,2007/1/10,D
ID,会員番号,日付,ステータス,承認
ソートがうまくいかず上記のように並んでいます。
理想としては
9,1023,2007/1/24,D
10,1023,2007/1/24,C
8,1023,2007/1/17,D
11,1023,2007/1/10,D
のように日付が新しい方を上にして書き込みたいのです。
2007/1/24のところのソートが上手くいきません。
また、IDの順序も変わると新しいIDをつけるときに困りそうです。
なにかいい方法があったら教えてください。
No.3ベストアンサー
- 回答日時:
Perlなんでいくらでも小難しく書けるのですが(シュオーツ変換とかで検索してみてください)、
できるだけわかりやすくなるように書いてみました。
#1の方の挙げられたスクリプトはsortのブロックの中で色々処理をしているので、
ソートに伴う比較の回数だけそれを行うことになるので、あまり速度面ではよろしくありません。
こういう場合、ソートのキーとなる部分を取り出して別個に配列に仕立て上げて
処理するのがよくある手段です(これを突き詰めていくとシュオーツ変換になります)。
ソートのキーが複数あり、それらの間で順位が決まっているなら sort のブロックの中で
・優先順位1のキーで比較 (今回の例では日付)
・比較結果が0以外ならそれを返し
・比較結果が0なら(同じ日付)優先順位2のキーで比較しその結果を返す
という手順をとればよいです。
use strict;
use warnings;
my @records = <DATA>;
#make sort key
my @primekeys;
my @subkeys;
foreach my $l (@records) {
my ($id, $date);
($id, undef, $date, undef) = split q{,}, $l, 4;
my ($y, $m, $d) = split q{/}, $date, 3;
push @primekeys, ($y*10000 + $m*100 + $d);
push @subkeys, $id;
}
my @sortedkeys = sort
{$primekeys[$b] <=> $primekeys[$a] || $subkeys[$a] <=> $subkeys[$b]}
0 .. $#records;
my @sortedrecords = @records[@sortedkeys];
print @sortedrecords;
__END__
2,1029,2007/1/15,C,
3,1029,2007/1/15,B,checked
4,1029,2007/1/10,D,
5,1029,2007/1/9,C,checked
6,1029,2007/1/16,D,
8,1023,2007/1/17,D
9,1023,2007/1/24,D
10,1023,2007/1/24,C
11,1023,2007/1/10,D
no3さんの方法で試したところうまくいきました。
一発で上手くいくとは思わなかったので驚きです。
ただ、no2さん、no1さん、せっかく回答頂いたのに
試さなくてすみません。
でも、アルゴリズムがわかりました。
みなさんありがとうございました。
No.2
- 回答日時:
色々な書き方があるかもしれませんが、最近私が書いたものです。
ソートブロックの中が込み入っている場合は、結果を求める関数
を別に作って呼び出すと、コードがすっきりします。
#!Perl
use File::Slurp;
my @data = read_file("A1.csv");
@data = sort { get_date($b) <=> get_date($a) } @data;
print @data;
sub get_date {
my $rec = shift;
my $ymd = (split /,/ => $rec)[2];
sprintf '%04d%02d%02d' => (split /\// => $ymd);
}
__END__
No.1
- 回答日時:
> ソートがうまくいかず
とあるので、ソート部分だけだと、
・各行を項目に分割し、
・日付を年月日に分割してyyyymmdd形式に統一し、
・それを降順でソート
というところがキモでしょうか・・良い方法かどうかは・・?
my @data = <CSV>; # @dataにCSVの全行が有るとして
chomp @data; # 必要なら各行末尾の改行コードを除く
@data = sort{
my $data_a
= join '', map{ sprintf("%02d",$_) } split /\//, (split /,/, $a)[2];
my $data_b
= join '', map{ sprintf("%02d",$_) } split /\//, (split /,/, $b)[2];
$data_b cmp $data_a # 日付は数字8桁なのでcmpは<=>でも可
} @data;
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) 結合セルのソートについて 5 2022/04/22 11:57
- Excel(エクセル) エクセルVBA オートフィルタでの絞り込みと並び替えについて 1 2023/07/08 13:08
- その他(プログラミング・Web制作) google formsを使ったタスク依頼フォーム作成におけるご相談 1 2023/06/22 15:55
- Yahoo!メール YahooIDをパスワード形式にしただけなのに、利用規約違反とされて電話番号が使えなくなりました 3 2023/03/25 04:08
- Visual Basic(VBA) Excel VBAで並べ替えをしたい 3 2023/02/25 09:31
- Excel(エクセル) 重複しているか否かをソートせずに判断する方法ありますか? 2 2022/07/06 21:16
- Yahoo!メール YahooIDをパスワード形式にしただけなのに、利用規約違反とされて電話番号が使えなくなりました 1 2023/03/15 20:44
- Excel(エクセル) Excelのソート(並べ替え) 2 2022/05/15 22:54
- Excel(エクセル) excel マクロでグループ内でソートしたい。見出しが上手くいきません。 7 2022/05/22 08:31
- gooポイント gooポイントをdポイントに交換できない。 3 2022/04/22 20:39
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
配列のサイズを動的に拡張
-
Pythonの再帰関数の動作の流れ...
-
文字列をカウントする方法
-
ファイル全てを .xlsm に変更し...
-
一定時間が経過したフォルダの削除
-
csvファイルの横方向への改行に...
-
while(<ハンドラ>) {} で行数を...
-
画像アップロード機能を追加し...
-
batファイルでrenameができませ...
-
while文がうまく動かない
-
VBAでCSVファイルの特定行を書...
-
MATLABのm-fileについて
-
ディレクトリのファイル作成を...
-
ANSI Cでファイル名、ディレク...
-
VB6.0でDB接続する際に切断時の...
-
AutoCADのスクリプト
-
C++でファイルから複数行のデー...
-
オープンしたファイルで行の連結
-
Perlで特定行から特定行までを...
-
連番のファイルを何個も開きたい
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
配列の中に重複文字列があるか...
-
C言語のバイナリモードでのfsca...
-
データの日付でソートをしたい
-
perlで複数行のデータを自由に...
-
perl-cgi 文字の長さでソートし...
-
Visual C++を用いたシリアル通信
-
バッチファイルの作り方(CSV→...
-
awkスクリプトでダブルクォーテ...
-
VBAでCSVファイルの特定行を書...
-
DOSコマンドで、標準出力を出力...
-
ExcelをCSV書き出す場合のシー...
-
openした後、closeしないでプロ...
-
close()で例外が投げられる理由
-
batファイルでrenameができませ...
-
VBAでCSVファイルを途中行まで...
-
window.open でのファイル指定方法
-
VBAで巨大なファイルの途中から...
-
Perlで特定行から特定行までを...
-
ReadLineでの読み出し行を指定する
-
エクセルVBAで素数だけを出力す...
おすすめ情報