• ベストアンサー

sort の極意

以下のようなファイル名が複数あります。 abcd_021106_0.txt abcd_021106_1.txt abcd_021106_2.txt abcd_021106_11.txt これを @list = glob("abcd_021106_*");で 取得すると、配列には、 (0) abcd_021106_0.txt (1) abcd_021106_1.txt (2) abcd_021106_11.txt (3) abcd_021106_2.txt というふうに格納されてしまいます。 これではまずいので、きちんと末尾の順番どおり sort するには どのようにすればいいのでしょうか。 よろしくご指南ください。

  • yasu
  • お礼率79% (173/218)
  • Perl
  • 回答数3
  • ありがとう数3

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

  • ベストアンサー
  • retr
  • ベストアンサー率75% (30/40)
回答No.2

急いで書いたので可読性が悪く、極意と言うほど一般化できませんでしたが、下記で出来ますよ。 ファイル名の形式が、「文字列_数字_数字.拡張子」となっている場合しか使えません。 形式が違う場合は、正規表現と、<=>、cmpを入れ替えて使ってください。 @orglist = glob("abcd_021106_*"); foreach (@orglist) { my ($nofi) = $_ =~ m/^(\w+)\.\w+$/; push(@tmplist, [$_, split("_", $nofi)]); } @newlist = sort {$a->[1] cmp $b->[1] || $a->[2] <=> $b->[2] || $a->[3] <=> $b->[3]} @tmplist; @list = (); foreach (@newlist) { push(@list, $_->[0]); } この時点で、@listに期待した順番でファイル名が入っているはずです。

yasu
質問者

お礼

スクリプトまでご紹介くださり、ありがとうございます。 そのまま貼り付ける形で実行できることを確認しました。 貴重な時間を割いていただき、感謝いたします。

その他の回答 (2)

  • leaz024
  • ベストアンサー率75% (398/526)
回答No.3

ご要望のソートは、次のスクリプトで実現できます。   @list = map {$_->[0]}                    # 3         sort {$a->[1] <=> $b->[1]}           # 2           map {[$_,/^abcd_\d{6}_(\d+)/]} @list;   # 1 これは、 1.元データと末尾の数値からなる"無名配列のリスト"を生成 2.末尾の数値で"無名配列のリスト"をソート 3.ソートされた"無名配列のリスト"から、元データを取り出す という流れになっています。 ファイルの命名規則が「名前_日付_番号.txt」となっているようですので、これを「名前順 かつ 日付順 かつ 番号順」でソートする場合、次のようにします。   @list = glob("*_*_*.txt");     # globのパターンも変える   @list = map {$_->[0]}         sort {$a->[1] cmp $b->[1] || $a->[2] <=> $b->[2] || $a->[3] <=> $b->[3]}           map {[$_,/^([a-z]+)_(\d{6})_(\d+)/]} @list; アルゴリズムについては、参考URLのページもご参考ください。

参考URL:
http://www.din.or.jp/~ohzaki/perl.htm#SortST
yasu
質問者

お礼

スクリプトと詳細に解説していただき、ありがとう ございます。ご紹介いただいた URL も 大いに参考に なりました。自分でも探したつもりでしたが、見つける ことができませんでした。 貴重な時間を割いていただき、感謝いたします。

  • taknt
  • ベストアンサー率19% (1556/7783)
回答No.1

ソートですが、下記のものが正しいですね。 そうならないように以下のように工夫してもらうしかないです。 (0) abcd_021106_00.txt (1) abcd_021106_01.txt (2) abcd_021106_02.txt (3) abcd_021106_11.txt 以上のように桁数をあわせてあげれば、あなたが思ったようにソートされます。

yasu
質問者

お礼

ありがとうございます。 このようなフォーマットにするのが正当なんですね。 以後、参考にさせていただきます。

関連するQ&A

  • ソート順の配列に順位表示する

    Perlで、大きいソート順になっている配列があります。 その中には重複しているデータもあります @list = (100,80,80, 50, 50, 45, 10, 0, 0, 0); のような配列を @ranking = (1,2,2, 4, 4, 6, 7,10,10,10); と順位を格納させたいです。 簡単な方法がありましたら、教えてください。

    • ベストアンサー
    • Perl
  • ソート処理

    ついこの間正規表現のことで質問させていただいたものです なんとか問題は解決しました それとは別にソート関連での質問があります 正規表現の前にソートについて質問してご回答を頂いてからそれを参考に試してみました http://oshiete1.goo.ne.jp/kotaeru.php3?q=1882190 です push で@tmpの内容を ($score,$filename,$title,$sentenceの順番に) 3.5 abc.txt あいうえお aaaaa 4.6 def.txt かきくけこ bbbbb 2.8 ghi.txt さしすせそ ccccc 5.1 jkl.txt たちつてと ddddd という風にしました このリストを @tmp = map {$_->[0]} sort {$a->[0] <=> $b->[0]} map {[$_, split /<>/]}@tmp; としたんですが結果は abc.txt あいうえお aaaaa def.txt かきくけこ bbbbb ghi.txt さしすせそ ccccc jkl.txt たちつてと ddddd 3.5 4.6 2.8 5.1 というふうになってしまいます これを スコア順に 5.1 jkl.txt たちつてと ddddd 4.6 def.txt かきくけこ bbbbb 3.5 abc.txt あいうえお aaaaa 2.8 ghi.txt さしすせそ ccccc としたいのですがうえのソースでは何がいけないんでしょうか??

    • ベストアンサー
    • Perl
  • 構造体のリストをソートしたい。

    ある名簿のリストを作りました。 以下のような構造体で、 typedef struct meibo{ char name[10]; int old; struct meibo *next; }MEIBO; これを、ポインタp->next->nameをたどっていって、名前が辞書順になるようにリストを作ったのですが、 これを年齢順にソートして表示させたいんです。 どんな方法があるんでしょうか? 一旦すべてを配列に格納して、クイックソート…とかも考えたのですが、すごく領域をとるし、なんか2度手間(最初から配列に順に格納していけばよかったなぁ・・・と。 それでもやっぱり最初から名列順にするときから配列に入れておくほうがいいのでしょうか? 教えてください。 (最初から年齢を比較してリストを作れば・・ってのはなしで、名列順のリストが存在するものとしてください。)

  • powershellでのソート

    powershellでのソート処理に関して教えてください。 list.csv F1,F2,F3 file01.txt,c:\dirA,100kb file20.txt,c:\dirC,100kb file100.txt,c:\dirG,100kb file200.txt,c:\dirG,100kb CSVで上記の様なデータがあり、F1のデータにおいて、 ファイル名の数字部分でソートしたいのですが、 意図したソートができません。 数字を考慮してのソートってどうやればよいでしょうか。 PS c:\>Get-Content .\list.csv|ConvertFrom-CSV |Sort-Object f1 F1 F2 F3 -- -- -- file01.txt c:\dirA 100kb file100.txt c:\dirG 100kb file20.txt c:\dirC 100kb file200.txt c:\dirG 100kb file01.txt→file02.txt→file100.txt→file200.txtの並びでソートさせたいです。 よろしくお願いします。

  • 配列のソート

    下記のような形でデータを取得し結果を配列に格納し、 降順にソートしたいのですが、いい方法が見つかりません。いい方法はあるでしょうか。よろしくお願いします。 テーブル構造(test) ID|name |point|area| ==================== 1 |Aさん|56 | A | 2 |Bさん|12 | B | 3 |Cさん|24 | B | 4 |Dさん|34 | B | $sql = "select * from test"; $result = mysql_query($strSQL); while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) { ここで配列に格納 } 配列への格納方法と、pointの降順にソートする 方法が知りたいです。 最終的に、Aさん、Dさん、Cさん、Bさんと なるようにしたいです。

    • ベストアンサー
    • PHP
  • 多次元配列のソート?

    お世話になります。 外部テキストに保存されているデータを読み込んで、任意のデータで並べ替えたいです。 data.txtには、次の様なデータが格納されてます。 namae<>なまえ<>23<>2008/04/01<> このデータから、なまえで並べ替えたり、日付で並べ替えたりしたいです。 ------------------------------------------------------------------------------------------------ $list = file("data.txt"); foreach ($list as $line) { //配列を設定 list($data01, $data02, $data03, $data04) = explode("<>", $line); print $data02 . ":" . $data04 . "<br>\n"; } ------------------------------------------------------------------------------------------------ 宜しくお願いします。

    • ベストアンサー
    • PHP
  • 1次元配列のソート方法

    配列のソートメソッドについて質問させていただきます。 VB.NET初心者なので日本語がおかしいかもしれませんが、宜しくお願いいたします。 データテーブルが格納されている配列があり、 その配列をソートしたいと思っています。 データテーブルの中に「NO」と「ID」というフィールドがあります。 NOで昇順し、NOが同じだったらIDの昇順でソートといったことがしたいのですが、 条件によっては上手くいきません。 よろしければ、教えていただけないでしょうか? また、もっと効率の良い方法とかありましたら、具体的はソース等教えていただけないでしょうか? 宜しくお願いいたします。 [例] workDT() ← 元のデータテーブル配列 Dim Datatable(workDt.Rows.Count-1) As DataTable ← ソート後のデータテーブル配列 Dim tmpDatatable(workDT.Rows.Count-1) As DataTable ← 途中で使うデータテーブル配列 Dim NO(workDT.Rows.Count-1) As Integer ← 元のデータテーブル配列の各「NO」フィールドを格納する配列 Dim ID(workDT.Rows.Count-1) As String ← 途中で使うデータテーブル配列の各「ID」フィールドを格納する配列 Dim Index(workDT.Rows.Count-1) As Integer ← インデックスに使用 ' IDでソート For i = 0 To workDt.Length - 1 ID(i) = workDt(i).Rows(0).Item("ID") Index(i) = i Next ' 配列をIDでソート Array.Sort(ID, Index) ' ソート後配列をテンプ配列に格納 For i = 0 To workDt.Length - 1 tmpDatatable(i) = workDt(Index(i)).Copy Next ' NOでソート For i = 0 To tmpDatatable.Length - 1 NO(i) = tmpDatatable(i).Rows(0).Item("NO") Index(i) = i Next ' 配列をNOでソート Array.Sort(NO, Index) ' ソート後配列を格納 For i = 0 To tmpDatatable.Length - 1 Datatable(i) = tmpDatatable(Index(i)).Copy Next これで各配列を初期化します。 workDTに5つのデータテーブルが入っていて workDT(0):ID=3、NO=1 workDT(0):ID=1、NO=5 workDT(0):ID=2、NO=5 workDT(0):ID=4、NO=5 workDT(0):ID=5、NO=7 (IDは重複不可設定、NOは重複可設定です。) とした場合、NOのソートのところで変な順番になってしまいます。 Array.Sort(NO, Index) このメソッドは同じ値だった場合、何を優先してソートしているのでしょうか? 環境はWindowsXPSP3とVB2005です。

  • あるディレクトリ内のファイルをファイル名でソートして取得

    _FindFirst や FindFirstFile を使用すると指定フォルダの ファイル名を順番に取得できるのですが、ファイル名でソートされていません。 ファイル名でソートして取得する関数(API)はあるのでしょうか?

  • iTunes9で「年別アルバム」でソートすると順番がばらばらに

    いつもお世話になっております。 今私はiTunes バージョン9.0.0.7.0を使用しているのですが どのプレイリストでも「年別アルバム」でソートしています。 しかし年別アルバムでソートすると、複数枚組のアルバムだと順番がばらばらになってしまいます。 言葉だとうまく表現できないので、スクリーンキャプチャした画像を添付します。 アルバム名や総ディスク枚数の数字、総トラック数の数字は統一してありますし、もちろんアーティスト名も同じです。 ちゃんと順番に表示されないのは何が原因なのでしょうか。 ちなみに、「アーティスト別」と「アルバム別」でソートすると、ちゃんと順番に表示されます。 また、コンピレーションの一部を「はい」にしても直りませんでした。 原因や解決法がお分かりの方、ご教示いただければ幸いです。 よろしくお願いします。

  • 多次元配列のソート2

    お世話になります。 昨日、質問して出来たと思っていたのですが、日付の方で並べ替えることが出来ませんでしたので、再度質問させて頂きます。 外部テキストに保存されているデータを読み込んで、任意のデータで並べ替えたいです。 data.txtには、次の様なデータが格納されてます。 namae<>なまえ<>23<>2008/04/01<> このデータから、日付で並べ替えたいです。 ------------------------------------------------------------------------------------------------ $list = file("data.txt"); foreach ($list as $line) { //配列を設定 list($data01, $data02, $data03, $data04) = explode("<>", $line); print $data02 . ":" . $data04 . "<br>\n"; } ------------------------------------------------------------------------------------------------ 宜しくお願いします。

    • ベストアンサー
    • PHP

専門家に質問してみよう