• 締切済み

perlのsortについて

下のテキストをグループ別でabc順にソートしたいのですが AG tanaka abe kaneda BG hayama oota endou CG kawai gennda hirata そのままsort関数を使用し、ソートをするとAG,BG,CGもソートされてしまい、さらに名前もAG,BG,CG関係なしにソートされてしまいます、 AG,BG、CGを動かさず、中身だけをソートする方法はないでしょうか?

みんなの回答

  • e_watt
  • ベストアンサー率71% (25/35)
回答No.3

個々の作業を安直にコードにして、 グループ名が来るたびに結果を吐き出す方法を採ってみました。 use strict; my @names = (); my $groupName = ''; while (<DATA>) { if (/^[A-Z]+$/) { # グループが始まるなら flush($_); # これまでの分を集計し、グループ名を更新 }else{ push @names, $_; # 名前は配列に追加 } } flush(''); # 入力の終了時にも集計 sub flush { if ($#names >= 0) { # 集計中の名前があれば print $groupName; map { print; } sort @names; # ソートして表示 @names = (); } $groupName = shift; # 新しいグループの名前 } __DATA__ AG tanaka abe kaneda BG hayama oota endou CG kawai gennda hirata

全文を見る
すると、全ての回答が全文表示されます。
  • kumoz
  • ベストアンサー率64% (120/185)
回答No.2

テキストを配列に入れれば、グループごとのスライスソートができると思います。なお、グループ名は大文字で、グループ内のテキストは大文字がないものとしています。 use strict; my @list = <DATA>; foreach my $end (0 .. $#list) { if ($end == $#list or $list[$end+1] =~ /[A-Z]/) { my ($start) = grep { $list[$_] =~ /[A-Z]/ } reverse 0 .. $end; @list[$start+1 .. $end] = sort @list[$start+1 .. $end]; } } print @list; __DATA__ AG tanaka abe kaneda BG hayama oota endou CG kawai gennda hirata

全文を見る
すると、全ての回答が全文表示されます。
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

方法1: AGに属すものだけのリスト抽出→ソート BGに属すものだけのリスト抽出→ソート→上のAGだけのソート済みのリストに追加 CGに属すものだけのリスト抽出→ソート→上のAGとBGをソート済みのリストに追加 と分割してやる。 方法2: ['AG','tanaka'] ['AG','abe'] 等とグループ+名前の状態でリストにする →グループを優先するようなソートを行う →グループと名前を分割する

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 重心の証明問題

    △ABCの重心をGとするとき、 AB^2+BC^2+CA^2=3(AG^2+BG^2+CG^2) となることを証明せよ という問題です。 2乗だから三平方? とかいろいろ試したのですが、分かりませんでした。 考え方のヒントだけでもいいので分かる方お願いします。

  • FMPro7『テキスト+数字』フィールドのソートができません。

    ファイルメーカーPro7でデータベースを作成し、シリアル番号を入力しています。 17ABC001、17ABC002、17ABC003 … という具合に『年度+固有記号+通し番号』としているのですが、 これを通し番号順にするためソートをかけたところ、まるででたらめに並んでしまいます。 フィールドタイプはテキストで、全て半角で入力してあります。 データベース作成途中に追加したフィールドなので、自動入力にはしてません。 どうしたら解決できますか? どなたか助けてください(>_<;)

  • 図形

    △ABCについて、2つの中線AD,BEの交点をGとし、AD=5cmとする。このとき、AGの長さはいくらでしょ? AD,BE,CFはいずれも中線で、点Gは重心。 よって AD/GD=BG/GE=CG/GF=2/1 AG:AD=2:3 まではわかるのですが どのようにしてAGの長さをもとめるのかがわかりません。 ADを求める方法をおしえてください

  • エクセル表で異なった分類でソートする方法

     A列に分類番号のA・B・Cを打ち、横にデータを記入していく。横列のC又はD(縦列)にア・イ・ウの頭文字をつけてデータ(人名や語句)を打っていく。このようにして作った表を、(1)ABCをソートして並べ替える(Aグループ、Bグループの順に並ぶ。次に(2)Aグループのなかを、アイウ順に並べ替えたい。そのような操作が出来る方法を教えてください。  私が試みたら、C列だけがソートされて、横のデータが付いていかないのです。空欄があるせいでしょうか。それとも?ソートは、C欄全体を選択し、「降順」をクリックしています、表全体(AからE,Fまで選択したら、どの指標で(AかCか)分からないと思って。  試行錯誤で使っています。どうぞ知恵を貸してください。

  • Firefoxのテキストボックス履歴を並び替えたい

    タイトル通りです。 現状、Firefoxのテキストボックスの入力履歴が、最終入力順になっています。 これを文字列順(abc...)にソートしたいと思っているのですが、そのような設定・アドオン等はあるでしょうか? 今使っているのはFirefox 3.6.3です。 よろしくお願いします。

  • SQL(oracle)での並べ替え

    SQL(oracle)での並べ替えで質問がございます。 TABLE:AAA NO, NAM,GNo, DATE ------------------ 1, abc, 3, 09/01 2, bcd, 2, 08/25 3, cde, 2, 08/23 4, def, 3, 09/05 5, efg, 1, 09/03 6, fgh, 3, 08/21 のようなテーブルがあったときに、下記条件で並べ替えを したいと思っています。 1.GNo毎に最小のDATEを抽出し、各Gnoの最小のDATEのうち   小さいGNoのグループでソート。 2.1で同一GNo内ではDATEが小さい順にソート。 つまり、上記の例では、各GNoの最小のDATEは、 1・・・09/03 2・・・08/23 3・・・08/21 なので、これからDATEの小さい順に、GNoが 3、2、1の順にソートをします。各GNo毎にもDATEが小さい順に ソートをするので、結果として、 NO, NAM,GNo, DATE ------------------ 6, fgh, 3, 08/21 1, abc, 3, 09/01 4, def, 3, 09/05 3, cde, 2, 08/23 2, bcd, 2, 08/25 5, efg, 1, 09/03 のような順番にしたいのです。この結果のようにするには、 どのようなSQLにすればよいでしょうか? よろしくお願いいたします。

  • 外接球について

    球Pに内接する四面体ABCDがある AB=BC=CA=a、CD=b、∠ACD=∠BCD=90゜とする 球Pの半径をa、bを用いて表せ という問題で以前質問させていただいて、「△ABCの外心をH、Hを通り△ABCに垂直な垂線GHが「GH=b/2」となる点Gをとると AG=BG=CG=DGを満たすので点Gは球Pの中心となります。(一部抜粋)」という回答を頂いたのですが、なぜこうなるのでしょうか?

  • エクセルで全組合せを抽出したい

    A1セルにA A2セルにB A3セルにC・・・とA10セルまで続きます。(A10セルはJ) これの重複無く全組合せを抽出する関数を教えてください。 2文字→AB,AC,AD,AE,AF,AG,AH,AI,AJ 3文字→ABC,ABD,ABE・・・ 4文字→ABCD,ABCE,ABCF・・・ 10文字→ABCDEFGHIJ よろしくお願いします。

  • クイックソートがうまくいかない

    クイックソートとはこういう仕様のソートのことです。 (1)バラバラの配列から基準値を設定する。 (2)前から順番に辿って行って基準値よりも大きいならば、基準値よりも後に移動、小さいならば、基準値よりも前に移動させる。(私のプログラムの場合は基準値を配列の一番目の数に設定しています。) (3)小さいほうと大きいほうの二つのグループに分かれたらまたそれらのグループごとにクイックソートにかける。 (4)二つのグループを分けることができなくなればソート完了。 自分で確かめてみたのですが、どうやら関数QuickSortの中でさらに再帰的にQuickSortにかけるときにバグが発生しているようです。ですが、なぜバグが起きるのかわかりません。 お手数ですが、よろしくお願いいたします。 #include<stdio.h> #include<stdlib.h> #include<time.h> #include<string.h> #define N 10 void QuickSort(char mi,char *hai,int youso) { char *shoubox; char *bigbox; int k=0; int q=0; int i,len,len2; /*もし配列haiの大きさが1ならば終了*/ if(strlen(hai)==1) { return; } /*配列の2番目から最後まで基準値からの大小により仕分けしていく。大きいならば、配列bigboxに小さい*/ /*ならば配列shouboxにそれぞれ入れる。*/ for(i=1;i<youso-1;i++) { if(hai[i]>mi) { bigbox[k++]=hai[i]; } else { shoubox[q++]=hai[i]; } } /*仕分け処理はここまで*/ /*小さいほうの配列と大きいほうの配列をそれぞれクイックソートにかける再帰処理。*/ QuickSort(shoubox[0],shoubox,q); QuickSort(bigbox[0],bigbox,k); /*それぞれのソートが完了したら、配列haiに「小さいほうの配列」→「基準値」→「大きいほうの配列」 の順に値を代入していく。*/ len=strlen(shoubox); for(i=0;i<len;i++) { hai[i]=shoubox[i]; } hai[len]=mi; len2=strlen(bigbox); for(i=(len+1);i<len+len2;i++) { hai[i]=bigbox[i]; } /*代入処理ここまで。*/ } int main(void) { char array[N]; char m; int i,val,j; srand(time(NULL)); /*(1~10)までの数字をランダムに入力する処理*/ for(i=0;i<N;i++) { do{ val=rand()%10; for(j=0;j<i;j++) { if(val+'0'==array[j]) { break; } } }while(j<i); array[i]=val+'0'; } /*ランダムに値を入力する処理ここまで*/ m=array[0]; /*値配列の最初を基準値mに設定*/ QuickSort(m,array,N); /*基準値、配列、要素数を実引数として、クイックソートを呼び出す。*/ /*昇順に並べ替えた配列arrayを出力する。*/ for(i=0;i<N;i++) { printf("array[%d]=%c\n",i,array[i]); } return 0; }

  • クイックソートがうまくいかない

    クイックソートの仕様はこうです。 (1)バラバラにランダムで入力した配列から基準値を設定する。 (2)前から順番に辿って行って基準値よりも大きいならば、基準値よりも後に移動、小さいならば、基準値よりも前に移動させる。(私のプログラムの場合は基準値を配列の一番目の数に設定しています。) (3)小さいほうと大きいほうの二つのグループに分かれたらまたそれらのグループごとにクイックソートにかける。 (4)二つのグループを分けることができなくなればソート完了。 動作させてみたところ関数QuickSortの中の「基準値より大きいか小さいかの仕分けの処理」の後で、再帰処理があるのですが、再帰ではなく無限ループになってしまっているようです。 自分では、この処理で無限ループをとめているつもりです。 if(youso==1) { return; } なぜこのようになってしまうのでしょうか お手数ですが、よろしくお願いいたします。 #include<stdio.h> #include<stdlib.h> #include<time.h> #include<string.h> #define N 10 int k,q; void QuickSort(char mi,char hai[10],int youso) { char shoubox[10]; char bigbox[10]; int i,len,len2; k=0,q=0; /*もし配列haiの大きさが1ならば終了*/ if(youso==1) { return; } /*配列の2番目から最後まで基準値からの大小により仕分けしていく。大きいならば、配列bigboxに小さい*/ /*ならば配列shouboxにそれぞれ入れる。*/ for(i=1;i<youso;i++) { if(hai[i]>mi) { bigbox[k++]=hai[i]; } else { shoubox[q++]=hai[i]; } } /*仕分け処理はここまで*/ /*小さいほうの配列と大きいほうの配列をそれぞれクイックソートにかける再帰処理。*/ QuickSort(shoubox[0],shoubox,q); QuickSort(bigbox[0],bigbox,k); /*それぞれのソートが完了したら、配列haiに「小さいほうの配列」→「基準値」→「大きいほうの配列」 の順に値を代入していく。*/ len=strlen(shoubox); for(i=0;i<len;i++) { hai[i]=shoubox[i]; } hai[len]=mi; len2=strlen(bigbox); for(i=(len+1);i<len+len2;i++) { hai[i]=bigbox[i]; } /*代入処理ここまで。*/ } int main(void) { char array[N]; char m; int i,val,j; srand(time(NULL)); /*(1~10)までの数字をランダムに入力する処理*/ for(i=0;i<N;i++) { do{ val=rand()%10; for(j=0;j<i;j++) { if(val+'0'==array[j]) { break; } } }while(j<i); array[i]=val+'0'; } /*ランダムに値を入力する処理ここまで*/ m=array[0]; /*値配列の最初を基準値mに設定*/ QuickSort(m,array,N); /*基準値、配列、要素数を実引数として、クイックソートを呼び出す。*/ /*昇順に並べ替えた配列arrayを出力する。*/ for(i=0;i<N;i++) { printf("array[%d]=%c\n",i,array[i]); } return 0; }