数字のソート方法とは?

このQ&Aのポイント
  • 数字のソート方法について教えてください。
  • 連番を崩さずに昇順に数字を並び替える方法を教えてください。
  • 具体的なデータを使って数字のソート方法を教えてください。
回答を見る
  • ベストアンサー

数字のソート

早速です。 以下のように頭に連番、 次の4項目が00~99までの数字の レコードがあります。 これを連番は崩さず、 4個の数字を昇順に並べたいのですが。 どのようにソート(コード)すれば宜しいでしょうか。 1<>8<>13<>27<>30<> 2<>20<>9<>1<>16<> 3<>5<>31<>36<>38<> 4<>52<>79<>18<>27<> 5<>23<>15<>9<>28<> 6<>38<>6<>45<>25<> ↓ 1<>8<>13<>27<>30<> 2<>1<>9<>16<>20<> 3<>5<>31<>36<>38<> 4<>18<>27<>52<>79<> 5<>9<>15<>23<>28<> 6<>6<>25<>38<>45<> 宜しくお願いします。

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

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

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

解決しましたか。よかったです。 ポイントですか。 具体的に何のポイントなのか、何を教えてほしいのかがちょっと分からないのですが・・・ コーディングする際の注意点などでしょうか。 とりあえず注意点、というか私がいつも考えていることは、いくつかに分けて考えることです。 あと常に一箇所に集中することです。 全体を見ず、現在の部分で何をやればいいのかということを考えて、必要な処理だけを書いていきます。 余談で、LinuxとかOSのソースコードは1000万行以上あるらしいので全て見ることは現実的に不可能に近い訳ですが。。。 http://slashdot.jp/linux/article.pl?sid=08/10/24/114203 それと、シュワルツ変換というものを知らなかったので調べてみたところ次のページを見つけました。 (Perlの例が載っててよかった。。。) http://www.wdic.org/w/TECH/%E3%82%B7%E3%83%A5%E3%83%AF%E3%83%AB%E3%83%84%E5%A4%89%E6%8F%9B これによると ------------------------------------ リストを、各要素に一定の演算を施したもので操作したいが、 最終的に必要なのが演算の結果ではなく、本来の要素である場合に用いる手法。 ------------------------------------ らしいので少なくともソートではないです(間違っていたらすみません)。 どうやって昇順(あるいは降順)に並べるか、という「ソートの手法(アルゴリズム)」ではなく、 上記のような状況に対する「コーディングの手法」みたいなもので、ソートは上記の文で言う「一定の演算」という部分にすぎません。 このページの例では、大文字小文字の区別をつけずにソートしたいが、 結果として表示するものは元の文字列にしたいというものです(結果がすべて大文字や小文字になっていたら変ですよね)。 そしてそれを実現するために、このコードでは 1. ソートする配列の要素を「元の文字列」とソートに必要な「全て小文字にした文字列」を要素にもつ「配列のリファレンス(ポインタのようなもの)」にして(一つにまとめる)、 ------------------------------------ map { [ $_, lc($_) ] } @unsorted ------------------------------------ 2. 大文字小文字の違いを無視するために、「全て小文字にした文字列」で比較し、ソートする ------------------------------------ sort { $a->[1] cmp $b->[1] } ------------------------------------ 3. ソートされた結果の「元の文字列」を取りだす ------------------------------------ map { $_->[0] } ------------------------------------ というようなことをしているようです。

nagahaha
質問者

お礼

kirikirikaz様、 またまた詳しく、さらに調べていただいてまで説明いただき、 有り難うございました。 シュワルツ変換はソートの例として出ていたので、 てっきりそうかなと思いましたが、勉強しなければいけないですね。 mapの目的も分かりました。 聞きたかったのは、 1レコードの中をソートするのと、 レコード自体をソートするのとでは、 書き方でどう違うのかというポイントでしたが、 シュワルツ変換はソートではないということで、 自分なりに研究してみます。 (前者は単純sortを、後者はシュワルツ変換を使うのかなと思っていました。) とにかく今はちゃんと動いております。 大変お世話になりました。 今後とも宜しくお願いいたします。 20点では申し訳在りませんが、それしか付けられないので。 有り難うございました。

その他の回答 (4)

回答No.4

2つ質問をさせてください。 まず最初に質問者さんは 連番<>数字1<>数字2<>数字3<>数字4<> のような行をソートしたいと仰いましたが実際は 連番<>数字1<>数字2<>数字3<>数字4<>数字5<>日付 のような行が続いているということでしょうか? それでソートしたいのは 数字1<>数字2<>数字3<>数字4<>数字5 の部分ということでよろしいでしょうか? 次に解決につながるかもしれないアドバイスなのですが、 Perlでは -------------------------------- sort { $a <=> $b } @trm23456 -------------------------------- これだけでは、@trm23456の値は変わりません。 @trm23456の値を変更するには、 -------------------------------- @trm23456 = sort { $a <=> $b } @trm23456 -------------------------------- と「ソートした結果」を再び代入する必要があります。 もし現状が「ソートしたつもりなのに、ソートされていない」という状態なのであれば、これで解決するかもしれません。

nagahaha
質問者

お礼

kirikirikaz様、 大変お手間を取らせております。 お陰様で解決しました。 まさにご指摘のとおりでございまして。 結果がソートされていると思いこんでおりましたので、 代入を無視しておりました。 また、質問と実際が違うのも申し訳在りませんでした。 (ご指摘1はそのとおりでございます。) 実際を書いても大変なので、 内容が違わないエッセンスだけ書かしていただきました。 (何時も要点が分かれば一から自分でコーディングしております) 今回の件は、 過去にシュワルツ変換というソートを勉強した折り、 @lines(今回の@trm23456)を予めソートしていたので、同じと勝手に思いこんでしまったモノです。 折角ここまで教えていただいたので、 トコトンと言うことで今少しお付き合いいただければ幸いです。 今回の例Aは、 データの中に例えば5回くじを引いた結果があり、 それを見やすくするために昇順に並べたという考え、 よってレコード(行)の順番は不変。 前回の例Bは、 例えば、徒競走と砲丸投げをやって個人毎に2つの結果があった場合、 徒競走の順位で表示したり、砲丸投げの順位で表示したりと、 レコードの順番が変わってしまうケースの違いなのですね。 そして今回教えていただいたのはAのケース、 シュワルツ変換を習ったのがBのケース。 格好は似ていますが、ここら辺について、 ポイントが聞ければ大変嬉しく思います。 これだけ教えていただいて厚かましいのですが、 お暇なときに宜しくお願いいたします。 もう解決したのですが、その後に本件をクローズいたします。 宜しくお願いします。 有り難うございました。

回答No.3

「1件」というのは「1行」のことでしょうか?「1つのファイル」のことでしょうか? それとも質問の冒頭でレコードと仰っているのでデータベースのことでしょうか? (私はデータベースは扱ったことがないのでもしそうだったら解答できない可能性がありますが。。。) あと分かっていたらすいませんが、DATAは__DATA__以下にあるテキストを読み込むものなので、 DATAの部分をもし標準入力でしたらSTDIN、またはオープンしたファイルに差し替える必要があります。

nagahaha
質問者

お礼

お世話になります。 何回も恐縮です。 まず、データはexcelで出力したモノで、シーケンシャルファイルです。 1行が(質問では、はしょりましたが)連番、5個の数字、日付で構成されています。 この構成のレコード(行)が複数行在ります。 open(IN,"$file"); @lines = <IN>; close(IN); で読み、  foreach $line (@lines) {    local($trm01,$trm02,$trm03,$trm04,$trm05,$trm06,$trm07) = split(/<>/,$line);    #連番、数字1、2、3、4、5、日付    と在って、 ここから$trm01~$trm05をソートしたかったのです。 それで教わった形を以下のようにしています。    @trm23456 = ($trm02,$trm03,$trm04,$trm05,$trm06); #配列を作りたい sort { $a <=> $b } @trm23456; #ソートしたい そして分からないので書けていませんが、 最終的には、@trm23456でソートした結果を、 また元の$trm02~$trm06に戻したいのです。 これが出来れば完成なのですが。 全く分からないで書いているので、頓珍漢と思いますが、 手が入れられるでしょうか。 お手数をおかけしますが、宜しくお願いいたします。

回答No.2

そうでしたか。学ぶ気のある人にいきなり解答を示す、誠意を愚弄するようなことをしてしまってすみません。 DATAは、開かれた入力ファイルと同じです。 DATAから読み込む(<DATA>)ことで __DATA__(または__END__)の下に貼り付けられたテキストをあたかも「入力用ファイル」として読み込むことができる便利なものです。 ------------------------- while (<DATA>) { ------------------------- まずこの行でDATAから1行だけ、$_という変数に読み込んでいます。 この$_という変数はPerlのソースの至る所で使われます(変数を指定しない場合にこの変数に入ることが多い) 明示的に読み込む変数を指定する場合は ------------------------- while (defined(my $line = <DATA>)) { ------------------------- と書くと$lineに1行だけDATAから読み込まれます。 myは(スコープを限定する)変数宣言の一種です。 もっとPerlを詳しく知りたくなったら調べてみてください。 そうして読み込んだ文字列を次の行によって、末尾の改行を削除しています。 ------------------------- chomp; ------------------------- これは ------------------------- chomp $_; ------------------------- と同じです。 引数が省略されるとこの変数が使われます(全部の関数でそうなるというわけではありませんが・・・) そして次の ------------------------- my ($renban, @nums) = split /<>/; ------------------------- は ------------------------- my ($renban, @nums) = split /<>/, $_; ------------------------- と同じです。 これによってsplitで$_の文字列を"<>"というセパレータで配列に分割しています。 そしてその配列の1番目を$renbanに、残りの配列(2,3,4,5番目)を@numsという配列に代入しています。 最後の ------------------------- print join('<>', ($renban, sort { $a <=> $b } @nums)) . "<>\n"; ------------------------- この行はいろんな処理を一度にしているのでいくつかに分けると ------------------------- sort { $a <=> $b } @nums; ------------------------- の部分で@numsを「数値」としてソートしています。 普通に ------------------------- sort @nums ------------------------- とすると「文字列」としてソートされてしまうので 1から10の配列が1, 10, 2, 3, ...とソートされてしまうなど不都合が起きてしまいます。 そうしてソートされた配列を ------------------------- join('<>', 配列) ------------------------- という部分で繋げて1つの文字列にします。 そうしてできた文字列の後ろに出力の結果を整えるため"<>\n"をくっつけて ------------------------- print 文字列 . "<>\n" ------------------------- としているわけです。 この動作をwhileによって1行ずつ行った結果、質問者さんの意図した結果になる、というわけです。 説明下手で所々説明を省いたので伝わるかどうか。。。

nagahaha
質問者

お礼

kirikirikaz様、 何回も有り難うございます。 さらに手取り足取り、嬉しいです。 書いていただいたことは全て目から鱗です。 そして分かったつもりでやってみましたがダメでした。 そっくりコピーしてもダメなのでしょうか。 (勿論全角の部分は半角スペースに置き換えましたが) また、私のロジックは現状1件ずつ読み込んで処理しています。 教わったことを租借しながら私のロジックに当てはめてやってみます。 たどたどしく進んでいるため、次のお礼は何時になるやら分かりませんし、 また質問させていただくかも知れませんが、 宜しくお願いします。 (明日になってしまうかも知れません) お世話になります。 どうも有り難うございました。

回答No.1

こういう時はセパレータ(区切り文字)で区切ってから操作(この場合はソート)するとやりやすいです --------------------------------- #!/usr/bin/env perl use strict; use warnings; while (<DATA>) {   chomp;   my ($renban, @nums) = split /<>/;   print join('<>', ($renban, sort { $a <=> $b } @nums)) . "<>\n"; } __DATA__ 1<>8<>13<>27<>30<> 2<>20<>9<>1<>16<> 3<>5<>31<>36<>38<> 4<>52<>79<>18<>27<> 5<>23<>15<>9<>28<> 6<>38<>6<>45<>25<> ---------------------------------

nagahaha
質問者

お礼

早速有り難うございます。 教えていただいたのですが、基本が分かっておらず、 質問させてください。 DATA,$renban,@numsはそれぞれ何を指すのでしょうか。 DATAはレコードの名前を書けばよいのでしょうか。 $renbanと@numsはこのまま書いておけばよいのでしょうか。 説明いただければ嬉しいです。 宜しくお願いします。

関連するQ&A

  • ファイルメーカーでソート後のレコード番号を取得する

    1000件データがあって、ソートして20件にしたとします。その20件に連番を1から振って、その数字をエクスポートしたいです。ソート後のレコード番号を取得できる関数があるならそれでもかまいませんし、エクスポートで直接連番が書き出せるならその方がもっと助かります。 方法をご存知でしたら、ぜひご回答よろしくお願いいたします。

  • クイックソートのソート

    2 8 7 1 3 5 6 4 という数字が並んでいて 4を基準に左から昇順にクイックソートするとしたら 2 8 7 1 3 5 6 4 2 8 7 1 3 5 6 4 2 8 7 1 3 5 6 4 2 1 7 8 3 5 6 4 (1) 2 1 3 8 7 5 6 4 2 1 3 8 7 5 6 4 2 1 3 4 8 7 5 6 8 というふうになりますが (1)の状態は8と7が交換されていますが これは間違いなのでしょうか 教科書に載っていたのですが

  • 数字文字列のソート方法

    文字列に数字を含むデータのソートを行うプログラムを C言語で作成したいのですが、どうすれば良いでしょうか? 具体的に言うと、a12、a2、a10という順序で並んでいる データを昇順にソートした場合にa10、a12,a2というように ソートせず、ちゃんとa2,a10,a12とソートされるように したいのですが、簡単にできるものでしょうか? 質問がわかりにくいかもしれないのですが、どうかご回答をお願いします。

  • ソートで

    get().sort(function() { return Math.round(Math.random()) - 0.5; }) はどういう意味ですか? ソートを return Math.round(Math.random()) - 0.5; でするようですが、 ランダムな数字を出してどうやってソートされるのですか? ソートは文字でか数値ででないのですか? http://memopad.bitter.jp/w3c/jsref/jsref_sort.html では >フォルトで、要素をアルファベットの昇順にソートします。 しかし、数値が正しくソートされません(40が5の前に来ます)。 数値をソートするためには、数を比較する関数を追加しなければなりません。 となっています。 ランダムな数字でソートはできるのですか? 使う意味を教えて下さい。 それから、-0.5をしてるのはどういう意味でしょうか?

  • ピボットテーブルを複数項目でソートしたい

    ピボットテーブルに展開したデータを、表示している複数の行項目 によりソートすることは可能でしょうか? 行項目として以下が設定されており、  1.科目  2.仕入先  3.購入種類 列項目としては  4.仕入月 データとしては  5.仕入金額 並べ替え変えたい順序としては、 科目毎の年間仕入金額が多い順の購入種類昇順としたいので、 以下のように設定したいのですが、 ピボットテーブル フィールド詳細オプションでは 1項目しかソート順に指定することができません。  1.科目昇順⇒5.合計/仕入金額降順⇒3.購入種類昇順 上記のようなソートを行う方法はありますでしょうか?

  • sortコマンドについて

    mako-kwnshともうします。 タブで区切られたテキストファイルの 1番目と4番目の項目の昇順にソートしたいのですが可能なのでしょうか?

  • sortコマンドについて

    Unixのソートコマンドを用いて複数ソートキーを指定し、 ソートキーに応じて昇順降順を指定することはできるでしょうか? 宜しくお願い致します。 第一ソートキー 昇順 第二ソートキー 降順 第三ソートキー 昇順 以下を試して見ましたがうまくいきませんでした。 sort -k 1.1,1.2 -r -k 1.4,1.6 -k 1.8,1.9 test.txt

  • バブルソートを入れたいのですが

    こんにちは、Perlを始めたばかりの初心者です。 さっそく質問の方失礼します。 乱数1~100までの数字のうち20個をとりだし配列にいれ、数字を昇順に入れ替えして昇順前と昇順後の数字を表示する問題なのですが。 @a[100]=(1..100); srand(time()); for($i=0 ; $i<20 ; $i++){ $a=int(rand(@a)); print"$a\n"; } と上記の乱数20個を取り出すことができたのですが、 そのあとの昇順させようとしてバブルソートを利用したいのですが、どのように組み込めばいいかわかりません。 どのように組み込めばいいのでしょうか? お答えの方ヨロシクお願いします。

    • ベストアンサー
    • Perl
  • 2次元配列のソート

    2次元配列のデータをソートしたいのですが方法がわかりません。初歩的な質問ですが、ご存知の方、よろしくお願いいたします。 (例) 商品コード、商品名、金額、有効期限のデータを以下のように持っています。 $data[0] = ("001", "商品A", 5200, "2004/5"); $data[1] = ("002", "商品B", 350, "2005/1"); $data[2] = ("003", "商品C", 10800, "2004/3"); ・・・・ データの項目(商品コード、商品名など)数は固定ですが、データ数、内容は変化します。 2次元配列でデータがあり、商品コードで降順にソート、金額で昇順にソートなどのソートを行う方法はありますか? No.760468 で同じような質問があり、array_multisort が回答としてあがっていましたが、上記データの場合ソートできないようなので質問させていただきました。 なお、環境によりデータベースを使用することはできません。

    • ベストアンサー
    • PHP
  • VBSでソート&ファイル分割

    VBScriptでCSVファイルを最大5件のレコードになるように ファイル分割しようとしています。 ただし、同じコードが複数のファイルに分かれないようにしたいです。 入力するCSVファイル(test_in.csv)は以下のような形式です。 (実際のファイルに項目行はありません) 連番,コード,フラグ,日付 01,0001,A,20091001 02,0002,A,20091001 03,0003,A,20091002 04,0001,U,20091003 05,0003,D,20091003 06,0004,A,20091003 07,0005,A,20091003 08,0001,D,20091005 09,0006,A,20091003 10,0006,A,20091003 ※入力ファイルに同じコードのレコードが5件を超えることはありません) 上記の入力ファイルの場合は以下の3つのファイルに分割することになります。 【test_out_001.csv】 01,0001,A,20091001 04,0001,U,20091003 08,0001,D,20091005 02,0002,A,20091001 【test_out_002.csv】 03,0003,A,20091002 05,0003,D,20091003 06,0004,A,20091003 07,0005,A,20091003 【test_out_003.csv】 09,0006,A,20091003 10,0006,A,20091003 ※コード"0003"のレコードは2件あるので、test_out_001.csvには出力せず、  test_out_002.csvに出力します。  コード"0006"についても同様でtest_out_003.csvに出力します。 処理の手順としては 入力ファイルのデータをコードでソートし、 1ファイルに5件を超えないように追加していくのかと思いますが、 ソートと5件制限はどのように記述すればよいでしょうか?

専門家に質問してみよう