【问题标题】:sorting an array on the first number found in each element根据每个元素中找到的第一个数字对数组进行排序
【发布时间】:2011-10-21 11:40:25
【问题描述】:

我正在寻求帮助对数组进行排序,其中每个元素都由“一个数字,然后是字符串,然后是数字”组成。我想对数组元素的第一个数字部分进行排序,降序(以便我首先列出较高的数字),同时还列出文本等。

我还是个初学者,所以也欢迎以下替代品

use strict;
use warnings;

my @arr = map {int( rand(49) + 1) } ( 1..100 ); # build an array of 100 random numbers between 1 and 49

my @count2;

foreach my $i (1..49) {

    my @count = join(',', @arr) =~ m/$i,/g; # maybe try to make a string only once then search trough it... ???
my $count1 = scalar(@count); # I want this $count1 to be the number of times each of the numbers($i) was found within the string/array.

    push(@count2, $count1 ." times for ". $i); # pushing a "number then text and a number / scalar, string, scalar" to an array.
}

#for (@count2) {print "$_\n";}
# try to add up all numbers in the first coloum to make sure they == 100

 #sort @count2 and print the top 7
@count2 = sort {$b <=> $a} @count2; # try to stop printout of this, or sort on =~ m/^anumber/ ??? or just on the first one or two \d

foreach my $i (0..6) {
 print $count2[$i] ."\n"; # seems to be sorted right anyway
}

【问题讨论】:

  • 恭喜您作为初学者使用use strictuse warnings
  • 请说明您真正想要做什么。你写了关于排序的文章,在代码中有一些关于计数的东西。如果您最终想要计算不需要排序的数字......但是请提供您要计算的字符串的示例。
  • 计数/总和对我来说只是一个评论晕,我还没有看到它...如果我不能解决它可能会在这里问...谢谢跨度>

标签: perl sorting


【解决方案1】:

首先,将数据存储在数组中,而不是字符串中:

# inside the first loop, replace your line with the push() with this one:
push(@count2, [$count1, $i]; 

然后你可以很容易地按每个子数组的第一个元素排序:

my @sorted = sort { $b->[0] <=> $a->[0] } @count2;

当你打印它时,构造字符串:

printf "%d times for %d\n", $sorted[$i][0], $sorted[$i][1];

另请参阅:http://perldoc.perl.org/perlreftut.htmlperlfaq4

【讨论】:

  • 谢谢 moritz,好像打印出来了。不过有一个错字:\npush(@count2, [$count1, $i]); ???
【解决方案2】:

按原样满足您的要求。您最好不要在字符串中嵌入计数信息。不过,我会把它当作一个学习练习。

请注意,我通过使用哈希进行计数来换取内存的简洁性和可能的​​速度。

但是,可以使用 Schwartzian Transform 优化排序。

编辑:仅使用绘制的数字创建结果数组

#!/usr/bin/perl

use strict; use warnings;

my @arr = map {int( rand(49) + 1) } ( 1..100 );

my %counts;
++$counts{$_} for @arr;

my @result = map sprintf('%d times for %d', $counts{$_}, $_),
             sort {$counts{$a} <=> $counts{$b}} keys %counts;

print "$_\n" for @result;

但是,我可能会这样做:

#!/usr/bin/perl

use strict; use warnings;
use YAML;

my @arr;
$#arr = 99; #initialize @arr capacity to 100 elements 

my %counts;

for my $i (0 .. 99) {
    my $n = int(rand(49) + 1); # pick a number
    $arr[ $i ] = $n;           # store it
    ++$counts{ $n };           # update count
}

# sort keys according to counts, keys of %counts has only the numbers drawn
# for each number drawn, create an anonymous array ref where the first element
# is the number drawn, and the second element is the number of times it was drawn
# and put it in the @result array

my @result = map  [$_, $counts{$_}],
             sort {$counts{$a} <=> $counts{$b} }
             keys %counts;

print Dump \@result;

【讨论】:

  • 感谢 Sinan Unur,目前这对我来说看起来很难,但我会努力的。我在其输出中也得到了一些重复的数字......
  • 啊,我忘了创建一个辅助数组。会这样做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-30
  • 1970-01-01
  • 1970-01-01
  • 2012-08-11
  • 2021-09-15
  • 1970-01-01
  • 2021-10-03
相关资源
最近更新 更多