![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?8acaa2e)
お世話になります。
ソートのテクニックについて教えていただきたく質問しています。
ソートをするに、パタンが二つあると思います。
例示パタン1;
一人が5回の試技を行い、結果を記録したレコードがあり、
5回の試技を昇順に列べてからリストする。
レコード形式;名前、試技1、試技2、、、試技5、試技平均
例示パタン2;
一人が砲丸投げとやり投げを行い、結果を記録したレコードがあり、
砲丸投げと、やり投げ毎に記録の良い順にリストする。
レコード形式;名前、砲丸投げ記録、やり投げ記録
上記パタン1では、データを頭から読み出しながら試技をソートすれば良く、
ソートに要するスペース(メモリ?)は少なくて済む。
パタン2では、予め全レコードについてソートしてからリストする必要があるため、
スペースが要求されると思います。
ここで質問です。
パタン2のような場合、どのようなテクニックを使えばよいのでしょうか。
実際に動かしているのですが、パソコンでは問題なくても携帯電話で動かすと、
”上限サイズを超えたので云々”とのエラーになります。
(シュワルツ変換というテクニックでソートしています。)
@lines = map {$_->[0]}
sort {$b->[11] <=> $a->[11] or $a->[1] <=> $b->[1]}
map {[$_, split /<>/]} @lines;
上記の場合、メモリに蓄えられてソートがされると思います。
一度外に書き出すようなテクニックの方が良いのでしょうか。
時間も掛からず、メモリも食わない方法が理想ですが、
そうも行かないと思います。
メモリを食わずに済む方法を教えてください。
宜しくお願いします。
No.2ベストアンサー
- 回答日時:
携帯からのアクセスだからといって、CGIを動作するサーバ側の状況が変わるとは思えないあたりは、回答者1さんと同意見ですが、
とりあえず perl でのソートのメモリ消費量削減について。
Schwartzian transform は、記述はシンプルですが、
ソート中に全データのコピーが発生するため、メモリ効率はあまり高くありません。(回答1のように分けて書いてもメモリ消費は同じです)
配列のインデックスだけをソートする方がメモリ消費量は少なくなります。
それと、各行のsplit後は、ソートに不要なデータを保持しないようにした方がいいでしょう。
そうすると、
---
@key = map { [ (split(/<>/))[0,10] ] } @lines;
@lines = @lines[ sort { $key[$b]->[1] <=> $key[$a]->[1] or $key[$a]->[0] <=> $key[$b]->[0] } 0..$#lines ];
---
といったコードになります。
(このコードでも計算量的には Swartzian transformと変わりません)
早速有り難うございました。
分からないながらに、お示しいただいたコードを貼り付けてみましたが、
エラーで動きませんでした。
貼り付けミスはないと思います。
全体がよく分かっているわけではありませんが、
keyだけソートするという主旨は分かったつもりです。
最後にある、 0..$#lines ]; の部分が分かりません。
(このまま貼り付けたのではいけないのでしょうか)
宜しくお願いします。
No.5
- 回答日時:
スクリプトのデバッグ、読みました。
こんなモノがあるのですね、今度やってみます。
というのも、先ほど動かなかったまま全く何もせず、
マシンを代えてみたら動いてしまいました。
原因は分かりません。
ただ、動きはしましたが、やはり携帯電話では最大サイズを超えた旨のエラーで止まってしまいます。
途中までは出ますので、何とか使えます。
有り難うございました。
ということで、
今度動かないようなことが在ればスクリプトのデバッグをやってみたいと思います。
お世話になりました。
No.4
- 回答日時:
ご質問に対する回答とはちょっと異なると思いますがエラーとSortの処理とはなんの関係もないように思います。
問題点は処理終了後に出力されるデータ(HTMLでしょうか?)の量が携帯のメモリ容量を超えているためではないかと思います。
携帯のブラウザ表示は少し前までは2kの壁といわれ、コンテンツファイルそのものをトータルで2kバイト以下に抑えないと機種によってはご質問のようなエラーメッセージを吐いて終了という結果になります。
最近では携帯の容量も増えはしましたが、古い携帯を後生大事に使っているやつもいるという可能性と、表示画面の小ささの制約から、一般的に携帯コンテンツはおのずと小さなコードで作るようになっております。
PCで表示させたコンテンツを画像ともどもセーブして、そのファイル容量をチェックし、携帯の限界を確認してみてはどうでしょう。
ソートテクニックに関しては、ソートアルゴリズムが専門ではない(学問の一分野にもなっているくらいなので)のでコメントのしようもありませんが、プログラムは動いてなんぼのものです。 早い、小さい、リソースが少ない、(クールなプログラム)にこした事はありませんが、動かないプログラムはディスクのゴミでしかないのも事実です。 まずは動くものを完成させ、その後にテクを駆使してクールに育ててゆくことをお勧めします。
早速有り難うございます。
全く同じデータを使い、シュワルツ変換を使わないで、
かつこれ以上の項目を表示している別プログラムは問題なく動いています。
よって、シュワルツ変換でメモリを食っているのかなと判断したのですが。
No.3
- 回答日時:
その「貼り付けた」というのを, (できれば全部, できなければ関連部分だけでいいので) 示すことはできませんか? またと, 「エラーが出た」というなら「どの行に対しどのようなエラーが出たか」を書くようにしてください (もちろん「エラーが出た行」も示す). そうでないと, 「どこでどのようなエラーが出ているのかを推測する」必要があり, それは回答者に余計な負担を与えるものとなります.
@lines = @lines[ sort { $key[$b]->[1] <=> $key[$a]->[1] or $key[$a]->[0] <=> $key[$b]->[0] } 0..$#lines ];
はわけると
@sorted_indices = sort { $key[$b]->[1] <=> $key[$a]->[1] or $key[$a]->[0] <=> $key[$b]->[0] } 0..$#lines;
@lines = @lines[@sorted_indices];
となります.
早速有り難うございます。
質問に書いたとおりですが、
@lines = map {$_->[0]}
sort {$b->[11] <=> $a->[11] or $a->[1] <=> $b->[1]}
map {[$_, split /<>/]} @lines;
は問題なく動いていまして、
この部分を教えていただいた下記の分、
@key = map { [ (split(/<>/))[0,10] ] } @lines;
@lines = @lines[ sort { $key[$b]->[1] <=> $key[$a]->[1] or $key[$a]->[0] <=> $key[$b]->[0] } 0..$#lines ];
に置き換えました。
そうしたところ、
cgi自体がエラーとなって動かなかったということです。
中に入っていないので、どの行とかになりません。
この内容で答えになりますでしょうか。
宜しくお願いします。
No.1
- 回答日時:
# split /<>/ と $a->[11] のからみが不明ですが、本題で無さそうなので気にしない事にします。
==============================
同じ CGI を同じ条件で閲覧したとき、PC と 携帯で CGI の正常/異常が変るのは考え難いと思います。
・使用したデータは同じですか?
・ブラウザ等の性質によって処理を振り分ける部分はありませんか?
・さらには、JavaScript では無く CGI のエラーってのは確かですか?
==============================
ご質問の件ですが、 map(sort(map())) とネストさせるとそれぞれの段階で無名配列がとられるかも知れません。 Perl が最適化で頑張ってくれれば良いのですが、そうで無ければ以下の様にステップを分けた方がメモリ使用は減ると思います。
@lines = map {[$_, split /<>/]} @lines;
@lines = sort {$b->[11] <=> $a->[11] or $a->[1] <=> $b->[1]} @lines;
@lines = map {$_->[0]} @lines;
まず sort の内部で split という高負荷処理をさせない、次にメモリ使用を減らすという考え方は、良いと思いますよ。
極めたいなら、Perl の sort() を使用せずに自分で書く手があります。 クイックソート・ラディックスソート・ヒストグラムソート とか、いろいろの手法からデータ傾向に合うものを選び、小メモリ化に腐心すれば良い結果が得られる*かも*知れません。
早速有り難うございます。
># split /<>/ と $a->[11] のからみが不明ですが、
済みません、私のコードをそのまま貼り付けました。
> CGI の正常/異常が変るのは考え難いと思います。
メモリ消費量等は変わらないかも知れませんが、
携帯電話では豊富にメモリが使えないのではと思っています。
お示しいただいたコーディングにしてみましたが、
(もちろん正しく動作しましたが)
携帯電話での結果は同じ、「上限サイズに云々」が出ました。
>Perl の sort() を使用せずに自分で書く手があります。
全くの素人で、例示いただいたコードを何とかアレンジして
試行錯誤すると言ったレベルです。
今後、勉強が必要です。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) 重複しているか否かをソートせずに判断する方法ありますか? 2 2022/07/06 21:16
- Excel(エクセル) 結合セルのソートについて 5 2022/04/22 11:57
- Excel(エクセル) Excel 効率的な名簿と得点の管理の仕方 8 2022/08/07 08:15
- Excel(エクセル) Excelの50音順ソートを全ての行列に適用するには? 4 2022/12/05 11:28
- Oracle Oracleですがsqlで質問です。 サブクエリ内で番号というカラムで昇順の1レコード目を取得したい 3 2023/05/22 10:02
- その他(職業・資格) 一級建築施工管理技士 手当てについて 3 2022/08/03 16:34
- Excel(エクセル) Excelで数式をそのままコピーしたい どうすればいいですか? 4 2022/09/16 02:16
- 仕事術・業務効率化 効率的な勉強方法(分野問わず)を教えてください 1 2023/08/16 01:33
- Visual Basic(VBA) Excel VBAで並べ替えをしたい 3 2023/02/25 09:31
- Excel(エクセル) エクセルでの色付け 5 2022/10/09 18:58
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
csvで順番の入れ替え
-
perlでの三次元配列の作り方
-
Listジェネリッククラスのやり...
-
ファイルから読み込んで配列へ
-
ダイアモンド演算子<>に対するb...
-
タブの色を変更する方法
-
重複ファイル名ある場合ファイ...
-
Perl初心者です。同一データを...
-
指定の行数目から行を抽出する
-
perlのflock関数でロックをかけ...
-
Net::FTPを使いファイル一覧の...
-
perlのエディタでおすすめを教...
-
データファイルからのデータの...
-
HTMLのフォームで画像と文...
-
レコードの書込み判断
-
Perlでファイルを読み込みタグ...
-
Pythonでテキストを行数指定し...
-
datファイルってなんですか?
-
フォルダーの深さの限界
-
htaccessで特定のディレクトリ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
どのようなプログラムをつくれ...
-
perlでの三次元配列の作り方
-
csvで順番の入れ替え
-
配列の中に重複文字列があるか...
-
perlで複数行のデータを自由に...
-
要素を削除する最適な方法
-
pushをすると行ができる
-
行・列の整理! perl
-
ファイルから読み込んで配列へ
-
Perlの初歩的な質問・・・
-
C言語のバイナリモードでのfsca...
-
C言語でバイナリファイルの読み...
-
perl-cgi 文字の長さでソートし...
-
Pythonの再帰関数の動作の流れ...
-
perlで読み込んだURLを配列に入...
-
CSVデータ「","」と「,」混在読...
-
perlの無名配列の使い方を教え...
-
ランダムでかぶらないように4...
-
ソートのテクニックについて
-
ログファイルの指定行に書込み
おすすめ情報