Arrays 散列列表的参数排序
我的目标是编写一个接受Arrays 散列列表的参数排序,arrays,perl,sorting,hash,Arrays,Perl,Sorting,Hash,我的目标是编写一个接受 散列数组 包含排序顺序的列表 我只是想说清楚,钥匙可能是任何东西。我的例子仅供参考 给定一个数组,其中包含按所需排序顺序排列的键列表 my @aSortOrder = ( 'DELTA1_2', 'SET1', 'SET2' ); 我的想法是组成一条线 $a->{DELTA1_2} <=> $b->{DELTA1_2} or $a->{SET1} <=> $b->{SET1} or $a->{SET2} <=
给定一个数组,其中包含按所需排序顺序排列的键列表
my @aSortOrder = ( 'DELTA1_2', 'SET1', 'SET2' );
我的想法是组成一条线
$a->{DELTA1_2} <=> $b->{DELTA1_2} or $a->{SET1} <=> $b->{SET1} or $a->{SET2} <=> $b->{SET2}
输出
我想这远不是解决问题的理想方法,因此任何关于如何更好地解决这个问题的指针都会有很大的帮助。好吧,你说得很对-像这样使用
eval
是一条通向未来痛苦的道路
“sort”的乐趣在于,您可以定义一个sort子程序,它隐式定义$a
和$b
并且您可以使用任何逻辑来决定它是正、负或“零”比较(相等)。(例如,如
或cmp
do)
这里的诀窍是-‘true’是任何非零的值,因此
您可以测试‘true’,以查看是否需要进行比较(4
是‘false’)
因此,如果您只是以数字方式工作(您需要测试“字母数字”并在某些情况下使用cmp
,但似乎不适用于您的数据):
注意,我选择将其用于输出,因为否则散列是无序的,因此转储程序的输出将不一致(随机排序的字段)
如果您需要更加动态地进行排序,可以将其传递到排序子节点:
#!/usr/bin/env perl
use strict;
use warnings;
sub order_by {
for my $key (@_) {
#compare key
my $result = $a->{$key} <=> $b->{$key};
#return it and exit the loop if they aren't equal, otherwise
#continue iterating sort terms.
return $result if $result;
}
return 0; #all keys were similar, therefore return zero.
}
my $paRecords = [
{ 'SET1' => 48265, 'DELTA1_2' => -1, 'SET2' => 48264 },
{ 'SET1' => 8328, 'DELTA1_2' => -29, 'SET2' => 8299 },
{ 'SET1' => 20, 'DELTA1_2' => 0, 'SET2' => 0 },
{ 'SET1' => 10, 'DELTA1_2' => 0, 'SET2' => 0 }
];
#qw is 'quote-words' and just lets you space delimit terms.
#it's semantically the same as ( 'DELTA1_2', 'SET1', 'SET2' );
my @order = qw ( DELTA1_2 SET1 SET2 );
print join( ",", @order ), "\n";
foreach my $record ( sort {order_by ( @order ) } @$paRecords ) {
#use hash slice to order output in 'sort order'.
#optional, but hopefully clarifies what's going on.
print join( ",", @{$record}{@order} ), "\n";
}
#/usr/bin/env perl
严格使用;
使用警告;
子订单由{
我的$key(@){
#比较键
my$result=$a->{$key}$b->{$key};
#返回它,如果它们不相等,则退出循环,否则
#继续迭代排序项。
如果$result,则返回$result;
}
返回0;#所有键都相似,因此返回0。
}
我的美元=[
{'SET1'=>48265,'DELTA1_2'=>1,'SET2'=>48264},
{'SET1'=>8328,'DELTA1_2'=>29,'SET2'=>8299},
{'SET1'=>20,'DELTA1_2'=>0,'SET2'=>0},
{'SET1'=>10,'DELTA1_2'=>0,'SET2'=>0}
];
#qw是“引用单词”,它只允许您用空格分隔术语。
#它在语义上与('DELTA1_2','SET1','SET2')相同;
my@order=qw(DELTA1_2 SET1 SET2);
打印联接(“,”,@order),“\n”;
foreach my$记录(排序{order_by(@order)}@$paRecords){
#使用哈希切片按“排序顺序”对输出排序。
#可选,但希望澄清发生了什么。
打印联接(“,”,@{$record}{@order}),“\n”;
}
好吧,你说得很对-像这样使用eval
是一条通往未来痛苦的道路
“sort”的乐趣在于,您可以定义一个sort子例程,它隐式地定义$a
和$b
,并且您可以使用您想要的任何逻辑来决定它是正比较、负比较还是“零”比较(相等)。(例如,如
或cmp
do)
这里的诀窍是-‘true’是任何非零的值,因此
您可以测试‘true’,以查看是否需要进行比较(4
是‘false’)
因此,如果您只是以数字方式工作(您需要测试“字母数字”并在某些情况下使用cmp
,但似乎不适用于您的数据):
注意,我选择将其用于输出,因为否则散列是无序的,因此转储程序的输出将不一致(随机排序的字段)
如果您需要更加动态地进行排序,可以将其传递到排序子节点:
#!/usr/bin/env perl
use strict;
use warnings;
sub order_by {
for my $key (@_) {
#compare key
my $result = $a->{$key} <=> $b->{$key};
#return it and exit the loop if they aren't equal, otherwise
#continue iterating sort terms.
return $result if $result;
}
return 0; #all keys were similar, therefore return zero.
}
my $paRecords = [
{ 'SET1' => 48265, 'DELTA1_2' => -1, 'SET2' => 48264 },
{ 'SET1' => 8328, 'DELTA1_2' => -29, 'SET2' => 8299 },
{ 'SET1' => 20, 'DELTA1_2' => 0, 'SET2' => 0 },
{ 'SET1' => 10, 'DELTA1_2' => 0, 'SET2' => 0 }
];
#qw is 'quote-words' and just lets you space delimit terms.
#it's semantically the same as ( 'DELTA1_2', 'SET1', 'SET2' );
my @order = qw ( DELTA1_2 SET1 SET2 );
print join( ",", @order ), "\n";
foreach my $record ( sort {order_by ( @order ) } @$paRecords ) {
#use hash slice to order output in 'sort order'.
#optional, but hopefully clarifies what's going on.
print join( ",", @{$record}{@order} ), "\n";
}
#/usr/bin/env perl
严格使用;
使用警告;
子订单由{
我的$key(@){
#比较键
my$result=$a->{$key}$b->{$key};
#返回它,如果它们不相等,则退出循环,否则
#继续迭代排序项。
如果$result,则返回$result;
}
返回0;#所有键都相似,因此返回0。
}
我的美元=[
{'SET1'=>48265,'DELTA1_2'=>1,'SET2'=>48264},
{'SET1'=>8328,'DELTA1_2'=>29,'SET2'=>8299},
{'SET1'=>20,'DELTA1_2'=>0,'SET2'=>0},
{'SET1'=>10,'DELTA1_2'=>0,'SET2'=>0}
];
#qw是“引用单词”,它只允许您用空格分隔术语。
#它在语义上与('DELTA1_2','SET1','SET2')相同;
my@order=qw(DELTA1_2 SET1 SET2);
打印联接(“,”,@order),“\n”;
foreach my$记录(排序{order_by(@order)}@$paRecords){
#使用哈希切片按“排序顺序”对输出排序。
#可选,但希望澄清发生了什么。
打印联接(“,”,@{$record}{@order}),“\n”;
}
只需创建一个进行比较的子对象
sub custom_cmp {
my $keys = shift;
for my $key (@$keys) {
my $cmp = $_[0]{$key} <=> $_[1]{$key};
return $cmp if $cmp;
}
return 0;
}
my @aSorted = sort { custom_cmp(\@aSortOrder, $a, $b) } @$paRecords;
只需创建一个进行比较的子对象
sub custom_cmp {
my $keys = shift;
for my $key (@$keys) {
my $cmp = $_[0]{$key} <=> $_[1]{$key};
return $cmp if $cmp;
}
return 0;
}
my @aSorted = sort { custom_cmp(\@aSortOrder, $a, $b) } @$paRecords;
传递给sort
的块可能包含任何数量的代码。只需根据$a
是否应被视为小于、等于或大于$b
计算为负数、零或正数即可
我同意您将其捆绑到子例程中的决定,因此我编写了按键排序散列
,它期望对散列数组的引用进行排序,并对键字符串数组进行引用。它返回根据键列表排序的哈希列表
使用严格;
使用“全部”警告;
使用数据::转储'dd';
我的$records=[
{SET1=>48265,DELTA1_2=>1,SET2=>48264},
{SET1=>8328,DELTA1\u 2=>-29,SET2=>8299},
{SET1=>20,DELTA1_2=>0,SET2=>0},
{SET1=>10,DELTA1_2=>0,SET2=>0}
];
我的@sort_order=qw/DELTA1_2 SET1 SET2/;
我的@sorted=sort\u按键散列($records,\@sort\u order);
dd\@已排序;
子排序\u按\u键散列\u{
我的($hash,$order)=@;
分类{
我的$cmp=0;
对于我的$key(@$order){
如果$cmp=$a->{$key}$b->{$key},则为最后一个;
}
$cmp;
}@$hash;
}
输出
[
{DELTA1_2=>-29,SET1=>8328,SET2=>8299},
{DELTA1_2=>
#!/usr/bin/env perl
use strict;
use warnings;
sub order_by {
for my $key (@_) {
#compare key
my $result = $a->{$key} <=> $b->{$key};
#return it and exit the loop if they aren't equal, otherwise
#continue iterating sort terms.
return $result if $result;
}
return 0; #all keys were similar, therefore return zero.
}
my $paRecords = [
{ 'SET1' => 48265, 'DELTA1_2' => -1, 'SET2' => 48264 },
{ 'SET1' => 8328, 'DELTA1_2' => -29, 'SET2' => 8299 },
{ 'SET1' => 20, 'DELTA1_2' => 0, 'SET2' => 0 },
{ 'SET1' => 10, 'DELTA1_2' => 0, 'SET2' => 0 }
];
#qw is 'quote-words' and just lets you space delimit terms.
#it's semantically the same as ( 'DELTA1_2', 'SET1', 'SET2' );
my @order = qw ( DELTA1_2 SET1 SET2 );
print join( ",", @order ), "\n";
foreach my $record ( sort {order_by ( @order ) } @$paRecords ) {
#use hash slice to order output in 'sort order'.
#optional, but hopefully clarifies what's going on.
print join( ",", @{$record}{@order} ), "\n";
}
sub custom_cmp {
my $keys = shift;
for my $key (@$keys) {
my $cmp = $_[0]{$key} <=> $_[1]{$key};
return $cmp if $cmp;
}
return 0;
}
my @aSorted = sort { custom_cmp(\@aSortOrder, $a, $b) } @$paRecords;
sub make_custom_cmp {
my @keys = @_;
return sub($$) {
for my $key (@keys) {
my $cmp = $_[0]{$key} <=> $_[1]{$key};
return $cmp if $cmp;
}
return 0;
};
}
my $cmp = make_custom_cmp(@aSortOrder);
my @aSorted = sort $cmp @$paRecords;
sub make_custom_cmp {
my @keys = @_;
my @cmps;
for $i (0..$#keys) {
push @cmps, "\$_[0]{\$keys[$i]} <=> \$_[1]{\$keys[$i]}"
}
return eval("sub($$) { ".( join(" || ", @cmps) )."}");
}
my $cmp = make_custom_cmp(@aSortOrder);
my @aSorted = sort $cmp @$paRecords;
my @aSorted =
map $paRecords->[ unpack('N', substr($_, -4))-0x7FFFFFFF ],
sort
map pack('N*', map $_+0x7FFFFFFF, @{ $paRecords->[$_] }{@aSortOrder}, $_),
0..$#$paRecords;