用第二个值(或总和)对“元组”进行排序

时间:2015-10-02 21:53:31

标签: python perl

我的目的是制作一个子程序,它取一个随机4-toops列表,排序 然后通过每个顶部从最大到最小的总和非破坏性地返回,并返回排序列表。

示例输出应为:

if(typeof ISCJS !== "undefined"){
   ISCJS.cl('init: selectNextChoice( option, ' + choice + ' )');

} else {
   console.log("ERROR: ISCJS is not defined");

}

这是我已经使用的代码的Python变体:

---- random 4-toops:
toop 1: (93 97 78 77); 345
toop 2: (-1 82 92 -45); 128
toop 3: (62 25 -31 -4); 52
toop 4: (-77 -86 18 36); -109
toop 5: (-72 -96 -83 -6); -257
---- random 4-toops sorted by sum:
toop 1: (93 97 78 77); sum = 345
toop 2: (-1 82 92 -45); sum = 128
toop 3: (62 25 -31 -4); sum = 52
toop 4: (-77 -86 18 36); sum = -109
toop 5: (-72 -96 -83 -6); sum = -257

所以我坚持这个问题:在Python中,我只是将我的总和列表和我的元组列表压缩在一起,然后按每个元组中的第二个元素排序,这总是总和。在perl中是否有一个等效函数可以根据元组的第二个元素进行排序?这是我到目前为止的尝试。

def sort_random_4_toops_by_sum(toops):
    summit = 0
    s = []
    for i in toops:
        summit = 0
        for d in xrange(0,4):
            summit += i[d]
        s.append(summit)
    together = zip(toops, s)
    sortedtog = sorted(together, key = lambda x: x[1],reverse=True)
    toops = [x[0] for x in sortedtog]
    return toops

告诉我这个:

sub sort_random_4_toops_by_sum {

    my ( @sorted_toops,@sorted_toops2, @sorted_toops_sums, @sortedtoops3 ) = @_;

    @sorted_toops2 = map { [ $_, sum( @$_ ) ] } @sorted_toops;
    @sorted_toops_sums = reverse sort { $a->[1] <=> $b->[1] } @sorted_toops2;

    my @sortedtoops3 = map { $_->[0] } @sorted_toops_sums;

    return \@sortedtoops3;
}

生成正确输出的测试代码:

Can't locate List/Tuples.pm in @INC

2 个答案:

答案 0 :(得分:2)

你那里的机器太多了。由于我无法理解您的代码,因此我将从头开始工作。我也会假设你的&#34; 4-tuples&#34;只是每个4个元素的数组引用,因为它们只需要它们。

use List::Util 'sum';

my @tuples = generate_a_bunch_of_random_tuples();

# Zip each tuple with its sum
my @tuples_with_sums = map { [ $_, sum(@$_) ] } @tuples;

my @sorted_with_sums = reverse sort { $a->[1] <=> $b->[1] } @tuples_with_sums;

my @sorted = map { $_->[0] } @sorted_with_sums;

事实上,可以在Schwartzian transform的实例中将整个事件作为单个语句来完成:

my @sorted = map { $_->[0] }
             reverse sort { $a->[1] <=> $b->[1] }
             map { [ $_, sum(@$_) ] }
             @tuples;

但为了便于理解,我把它写了很长的路。

A&#34; zip&#34; (如果你已经拥有多个并行列表,那么你可以从List::MoreUtils得到)。如果输出列表的每个元素都依赖于单个输入列表中的一个元素,map也可以正常工作 - 事实上,更好。

答案 1 :(得分:2)

首先,他们是 tupes 。我以前从未见过“toop”曾经是指数学或编程中的元组

您自己的代码存在的问题是您将sort_random_4_toops_by_sum的参数复制到了错误的位置。

my @sorted_toops = ();
my ( @sorted_toops2, @sorted_toops_sums, @sortedtoops3 ) = @_;

并且代码需要(名称非常糟糕的)@sorted_toops中的未排序的数据。您还要声明@sortedtoops3两次。如果您将其更改为如下,则程序将正常运行

sub sort_random_4_toops_by_sum {
    my @sorted_toops = @_;
    my ( @sorted_toops2, @sorted_toops_sums, @sortedtoops3 );

    @sorted_toops2 = map { [ $_, sum( @$_ ) ] } @sorted_toops;
    @sorted_toops_sums = reverse sort { $a->[1] <=> $b->[1] } @sorted_toops2;

    @sortedtoops3 = map { $_->[0] } @sorted_toops_sums;

    return \@sortedtoops3;
}

我建议您使用List::UtilsBy模块,该模块提供rev_nsort_by(反向数字排序)实用程序功能。使用它,您可以将sort_random_4_toops_by_sum缩减为此

use List::UtilsBy qw/ rev_nsort_by /;

sub sort_random_4_toops_by_sum {
    [ rev_nsort_by { sum @$_ } @_ ];
}