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;