在Perl中使排序稳定

时间:2013-07-11 12:59:17

标签: perl sorting

我和我有一系列裁判。像

这样的东西
$a[0] = [qw( 1 2 3 4 )];
$a[1] = [qw( a b c d )];

1234实际上是用于导航的网站面包屑(HomeProfile,{ {1}},Contact-us)。

现在,我必须对这个阶梯进行排序(并且在perl 5.8中使用稳定排序不是一个可悲的选择)

排序标准是

  1. 梯子的深度
  2. 如果两个梯子的深度相同,则根据它们的指数对它们进行排序。
  3. 例如,如果数组最初包含

    Contact-me-specifically

    然后在排序后,数组应该包含

    $a[0] = [qw( 1 2 3 4 )];
    $a[1] = [qw( 1 2 3 )];
    

    但如果数组如下: -

    $a[0] = [qw( 1 2 3 )];
    $a[1] = [qw( 1 2 3 4 )];
    

    然后排序后,

    $a[0] = [qw( 1 2 3 )];
    $a[1] = [qw( a b c )];
    

    我无法以这种方式工作,我尝试过。

    $a[0] = [qw( 1 2 3 )];
    $a[1] = [qw( a b c )];
    

    有人可以帮助我吗?

3 个答案:

答案 0 :(得分:4)

您的数据结构(链接列表)的描述以及sort例程(arrayrefs)中的实现并不完全适合;我将假设后者。

通过按位置排序作为次要标准,可以使非稳定排序稳定:

sort { normally or by_index } @stuff

通常,您似乎想要比较数组长度。为了能够测试索引,您必须以某种方式使当前元素的索引可用。您可以通过两种方式实现:

  1. 执行Schwartzian变换,并使用其索引对每个元素进行注释。这太傻了。
  2. 对索引进行排序,而不是元素。
  3. 这看起来像是:

    my @sorted_indices =
      sort { @{ $array[$b] } <=> @{ $array[$a] } or $a <=> $b } 0 .. $#array;
    my @sorted = @array[@sorted_indices]; # do a slice
    

    您之前使用$a <=> $b做的事情是比较引用。这并不能保证做任何有意义的事情。

    测试sort

    use Test::More;
    my @array = (
      [qw/1 2 3/],
      [qw/a b c/],
      [qw/foo bar baz qux/],
    );
    my @expected = (
      [qw/foo bar baz qux/],
      [qw/1 2 3/],
      [qw/a b c/],
    );
    
    ...; # above code
    is_deeply \@sorted, \@expected;
    done_testing;
    

答案 1 :(得分:2)

您的代码不起作用,因为您希望$a$b在一个地方(@$b <=> @$a)包含元素的值,而在另一个地方包含元素的索引($a <=> $b )。


您需要比较中的索引,因此您的比较函数将需要索引。

通过将数组的索引传递给sort,您可以访问索引和这些索引处的值,因此您的代码将包括

sort { ... } 0..$#array;

在我们完成排序之后,我们想要检索这些索引的元素。为此,我们可以使用

my @sorted = map $array[$_], @sorted_indexes;

my @sorted = @array[ @sorted_indexes ];

总之,我们得到:

my @sorted =
   map $array[$_],
    sort { @{ $array[$a] } <=> @{ $array[$b] } || $a <=> $b }
      0..$#array;

my @sorted = @array[
   sort { @{ $array[$a] } <=> @{ $array[$b] } || $a <=> $b }
     0..$#array
];

答案 2 :(得分:1)

我认为我们需要清理你的排序算法。你说:

  1. 梯子的深度
  2. 根据索引对它们进行排序。
  3. 以下是一个例子:

    $array[0] = [ qw(1 a b c d e) ];
    $array[2] = [ qw(1 2 b c d e) ];
    $array[3] = [ qw(a b c) ];
    $array[4] = [ qw(a b c d e) ];
    

    你希望他们按照这种方式排序:

    $array[3] = [ qw(a b c) ];
    $array[2] = [ qw(1 2 b c d e) ];
    $array[0] = [ qw(1 a b c d e) ];
    $array[4] = [ qw(a b c d e) ];
    

    这是对的吗?

    这个怎么样?

    $array[0] = [ qw(100, 21, 15, 32) ];
    $array[1] = [ qw(32,  14, 32, 20) ];
    

    按数字排序,$array[1]应在$array[0]之前,但按字符串$array[0]排序在$array[1]之前。

    另外,你注意到我无法判断$array[0]是否应该在$array[1]之前或之后,直到我查看数组的第二个元素。

    这使得在单行功能上很难进行排序。即使你可以以某种方式减少它,它也会让某人很难分析你在做什么,或者让你调试声明。

    幸运的是,您可以使用整个子例程作为排序例程:

    use warnings;
    use strict;
    use autodie;
    use feature qw(say);
    use Data::Dumper;
    
    my @array;
    $array[0] = [ qw(1 2 3 4 5 6) ];
    $array[1] = [ qw(1 2 3) ];
    $array[2] = [ qw(a b c d e f) ];
    $array[3] = [ qw(0 1 2) ];
    
    my @sorted_array = sort sort_array @array;
    say Dumper \@sorted_array;
    
    sub sort_array {
        #my $a = shift;   #Array reference to an element in @array
        #my $b = shift;   $Array reference to an element in @array
    
        my @a_array = @{ $a };
        my @b_array = @{ $b };
    
        #
        #First sort on length of arrays
        #
        if ( scalar  @a_array ne scalar  @b_array ) {
            return scalar @a_array <=> scalar @b_array;
        }
    
        #
        # Arrays are the same length. Sort on first element in array that differs
        #
        for my $index (0..$#a_array ) {
            if ( $a_array[$index] ne $b_array[$index] ) {
                return $a_array[$index] cmp $b_array[$index];
            }
        }
        #
        # Both arrays are equal in size and content
        #
        return 0;
    }
    

    返回:

    $VAR1 = [
              [
                '0',
                '1',
                '2'
              ],
              [
                '1',
                '2',
                '3'
              ],
              [
                '1',
                '2',
                '3',
                '4',
                '5',
                '6'
              ],
              [
                'a',
                'b',
                'c',
                'd',
                'e',
                'f'
              ]
            ];
    
相关问题