No.7ベストアンサー
- 回答日時:
最初に、回答に書き間違いが2カ所あったことをお詫びします。
1) 上から5行目: $a->[2] <=> $b[2] ---> $a->[2] <=> $b->[2]
2) 下から3行目: $y[$a] cmp $y[$a] ---> $y[$a] cmp $y[$b]
配列のソートには要素そのものを並べ替えるほかに、
配列の添字 (インデックス) を並べ替えるやり方があります。
@x = ("A", "B", "C", "B", "A");
1) @sorted = sort { $a cmp $b } @x; # { $a cmp $b } は省略可
2) @order = sort { $x[$a] cmp $x[$b] } 0 .. $#x;
sort では、$a と $b は特別な意味を持っています。$a と $b には、
ソート対象のリストのうちの2つの要素がセットされます。grep, map
の $_ と同じようなもので、sort では同時に2つの要素を処理するため
このようになっているものと思います。
2) のソートブロック { $x[$a] cmp $x[$b] } の $x[$a], $x[$b] は、配列
@x の各要素を指しています。配列名に @a または @b を使うと、各要素を
指定する $a[$a], $a[$b], $b[$a], $b[$b] のブラケット外の $a, $b は配
列名とは解釈されません (なお、@c は差し支えありません)。
ソートを行っている部分は、<=> のところだけではなく cmp によっても
行っています。
{ $a cmp $b } # 文字列比較
{ $a <=> $b } # 数値比較
sort { $x[$a] cmp $x[$b] or $y[$a] cmp $y[$b] or $z[$a] <=> $z[$b] } 0 .. $#x;
上のソートブロックでは、3つの比較文を or で繋げています。まず最初に、
@x の各要素を文字列比較して、同じ場合は結果が偽になりますので、次に
@y の同じ添字の要素を文字列比較して、それでも同じときには @z の同じ
添字の要素を数値比較せよ、という意味になります。
最後の質問ですが、質問を誤解しているかも知れません。
@v = (44, 33, 55, 22, 11);
@w = ("a", "b", "c", "b", "a");
@x = ("A", "B", "C", "B", "A");
@y = ("Y", "X", "Z", "X", "Z");
@z = (4, 3, 5, 2, 1);
@order = sort { $x[$a] cmp $x[$b] or $y[$a] cmp $y[$b] or $z[$a] <=> $z[$b] } 0 .. $#x;
@v = @v[@order]; @w = @w[@order];
@x = @x[@order]; @y = @y[@order]; @z = @z[@order];
ありがとうございます。
非常に参考になりました。
sortでは、$a,$bは予約変数になることは知りませんでした。
前回の回答で私なりに応用してやってみたのですが、最後の
質問部分は、連想配列に格納すれば、キー3つでソートする
と、自動で他の部分もソートされることが分かりました。
perlでは2次元配列は非常に見にくいので連想配列は非常に
便利です。
No.6
- 回答日時:
みなさんと似たような回答ですが、
print join "\n",
map { join(',', @$_) }
sort { $a->[0] cmp $b->[0] or $a->[1] cmp $b->[1] or $a->[2] <=> $b[2] }
map { [ $a[$_], $b[$_], $c[$_] ] } 0 .. $#a;
print "\n";
質問の配列名を変えれば、もう少し簡単になります。
配列名とソートのデフォルト変数の名前が衝突して、
ソートブロック内で配列の個々の要素を指定できない問題がある。
@x = ("A", "B", "C", "B", "A");
@y = ("Y", "X", "Z", "X", "Z");
@z = (4, 3, 5, 2, 1);
foreach (sort { $x[$a] cmp $x[$b] or $y[$a] cmp $y[$a] or $z[$a] <=> $z[$b] } 0 .. $#x) {
print "$x[$_],$y[$_],$z[$_]\n";
}
この回答への補足
皆様、お返事が大変遅くなりまして申し訳ありません。
かなり単純にできることが分かったのですが、いくつか追加質問をさせてください。
この例でいくと、@x,@y,@zで定義していますが、$a,$b,$cが必要になるのはどうしてでしょうか?
あと、ソートしたい配列が5個になった場合(キーは3つ)は対応可能でしょうか?
ソートを行っている部分は、<=>のところだと思われますが、キーにならない配列を同時に入れ替えることは可能ですか?
No.4
- 回答日時:
my @a = ("A","B","C","B","A" );
my @b = ("Y","X","Z","X","Z" );
my @c = (4,3,5,2,1);
# 作業用
my @array;
# ソートしたい配列達の同位置をだんご3兄弟でリファレンスにする
push@array, [ $a[$_], $b[$_], $c[$_] ]for 0..$#a;
# それをソートする
@array = sort { $a->[0] cmp $b->[0] || $a->[1] cmp $b->[1] } @array;
# 確認する
print Dumper( @array );
# 元の配列に戻す
($a[$_],$b[$_],$c[$_]) = @{$array[$_]}for 0..$#array;
# 確認する
print Dumper( @a,@b,@c );
# オンメモリなのでデータ容量が問題だったりして・・
No.3
- 回答日時:
@a = ("A","B","C","B","A" );
@b = ("Y","X","Z","X","Z" );
@c = (4,3,5,2,1);
for (sort{$a[$a] cmp $a[$b] or $b[$a] cmp $b[$b] or $c[$a] <=> $c[$b]} 0 .. $#a){
print "$a[$_],$b[$_],$c[$_]\n";
}
No.2
- 回答日時:
こちらをご参考に。
http://www.din.or.jp/~ohzaki/perl.htm#SortMulti
結果的に、2次元配列に変換したほうが楽だと思います。
for($i = 0; $i < @a; $i++){
push(@newArray,[$a[$i],$b[$i],$c[$i]]);
}
これで2次元配列にできますから、あとは
@newArray = sort{$a->[0] cmp $b->[0] or $a->[1] cmp $b->[1] or $a->[2] cmp $b->[2]} @newArray;
というようにソートしたい項目順にorで区切ってsort関数に入れ込めば良いでしょう。
No.1
- 回答日時:
単純な方法では無理です。
俺はこれを実現するために、データベースのエンジンシステムを組みました(笑)(しかも Perl で!!)
まぁ、そこまではいかずとも、2次元配列化して「最優先項目でまずソート」「キーが重複する要素だけ2番目の優先項目でソート」といったような処理が必要になるでしょう。
この回答への補足
やはり、単純には行きませんか…
どうもC言語感覚で考えると、for文で3回入れ子にしないと
できないかなぁ~と考えていたのですが、Perlだと思ってもみない
解決法がありそうで質問してみたのですが、重複する要素の位置を
把握してソートする必要がありますよね?
このあたりがものすごく処理に時間がかかったりするのか不安です。
ちなみに、1配列あたりでデータは最大1000件くらいです。
キーは3つですが、配列自体は20個近くになるため、最初はmysqlに
やらせようと思いましたが、group化が複雑になるので、perlで処理
できないものか考えていました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) Excelの50音順ソートを全ての行列に適用するには? 4 2022/12/05 11:28
- Excel(エクセル) 結合セルのソートについて 5 2022/04/22 11:57
- Excel(エクセル) 重複しているか否かをソートせずに判断する方法ありますか? 2 2022/07/06 21:16
- Excel(エクセル) Excel 効率的な名簿と得点の管理の仕方 8 2022/08/07 08:15
- Visual Basic(VBA) Excel VBAで並べ替えをしたい 3 2023/02/25 09:31
- その他(Microsoft Office) Excel関数での質問です 1 2022/11/22 13:06
- その他(プログラミング・Web制作) sortの優先キーについて(スプレッドシート) 1 2023/01/17 17:59
- Microsoft ASP プログラミング関係で質問です。 3 2022/10/11 16:06
- Java Java配列の問題を教えてください。 乱数で20個出力し、最大、最小、合計、平均を求め、更に昇順にソ 3 2023/07/10 18:32
- Visual Basic(VBA) Excel VBA キーワードから列を取得して、さらに空欄行を非表示にする 3 2022/10/21 22:49
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
perlで2次元配列をサブルーチ...
-
Excel VBA ユーザーフォームの...
-
VBAのautofilter、criteriaの配...
-
マクロ Publicでの配列定義
-
二次元配列のインデックスについて
-
リストボックスに縦スクロール...
-
配列を初期化する時ってどうす...
-
Excel(VBA)で配列の要素数を...
-
perlで配列の要素が空なのを知...
-
Dim flag(4) as boolean で配列...
-
ファイル名に日付・時刻を付与...
-
エクセルVBAでTransposeの不思議
-
VBA 多次元配列を用いてグルー...
-
perl 配列の要素数について
-
重複しない乱数発生
-
二次元配列における要素数のは...
-
fortran
-
perl このテキストファイルを簡...
-
jcode->jfold で禁則処理
-
可変長配列を、動的確保した固...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
二次元配列のインデックスについて
-
VBAのautofilter、criteriaの配...
-
Excel VBA ユーザーフォームの...
-
二次元配列における要素数のは...
-
マクロ Publicでの配列定義
-
Strawberry Perl for Windows ...
-
リストボックスに縦スクロール...
-
クラスに配列を渡す方法
-
Dim flag(4) as boolean で配列...
-
エクセルVBAでTransposeの不思議
-
perlで2次元配列をサブルーチ...
-
perlで配列の要素が空なのを知...
-
perl 配列の要素数について
-
組み合わせについての質問です...
-
隣同士の数字を足し合わせる
-
複数の配列の全ての組み合わせ...
-
perl 初等プログラミングについて
-
jcode->jfold で禁則処理
-
一致する要素が格納されている...
-
チェックボックスのperlでの値...
おすすめ情報