【问题标题】:Perl: Sorting 2D array with multiple columns based on a particular columnPerl:基于特定列对具有多列的二维数组进行排序
【发布时间】:2012-05-06 06:52:36
【问题描述】:

伪代码:

my @unsortedArray = { ["Harry", 10], ["Tim", 8], ["Joe", 3]};
my @sortedArray = ?????

最终的 sortedArray 应该基于 col-2(整数)进行排序,注意与“人名”(col-1)的一对一关系。最终结果应如下所示:

sortedArray should be { ["Joe", 3], ["Tim", 8], ["Harry", 10] }; 

【问题讨论】:

  • @array = { ... } 是(几乎总是)不正确的语法。使用@array = ( ... ) 分配给数组。
  • @mob : 我想知道当你提到 almost 时你想到了什么边缘情况 :)
  • @Zaid: @array_containing_a_single_hashref = { ... }

标签: arrays perl perl-data-structures


【解决方案1】:

你可以给sort一个谓词,即:一个函数,它被计算来比较列表中的元素。

my @unsorted = ( ["Harry", 10], ["Tim", 8], ["Joe", 3] );

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

在谓词(大括号中的表达式)中,$a$b 是要比较的外部列表的元素。

sort只关心一维列表,所以不会弄乱外部列表元素的内部结构。这样名字和号码之间的关系就被毫不费力地保留了。

请参阅perldoc -f sortperldoc perlop 了解更多详情。

【讨论】:

  • 我的@sorted = sort { $a->[1] > $b->[1] } @unsorted;更容易理解
  • 谢谢。有效。我只使用“排序”,它只对第二列进行排序。
  • @Mike 不,那是错误的 - vanilla sort 的谓词更像 { "$a" cmp "$b" },所以您会将 "ARRAY(0x2229d48)""ARRAY(0x2229d98)" 进行比较。与第二列排序的任何相似之处纯属巧合。
  • @askovpen - 如果$a 小于$b,这将不起作用,并且不能保证$a 在数组中早于$b<=> 和它的基于文本的表亲 cmp) 是仅用于 sort 函数的特殊运算符。尝试排序qw(2 5 28 3 1 62 4 81)。我得到1, 2, 5, 3, 28, 62, 4, 81 按照你的方式去做。
  • 同意 David W. askovpen 的评论是错误的,更难理解
【解决方案2】:

一个更有效的解决方案,尤其是对于更大的数组,可能是使用List::UtilsBy::nsort_by

use List::UtilsBy qw( nsort_by );

my @unsorted = ( ["Harry", 10], ["Tim", 8], ["Joe", 3] );

my @sorted = nsort_by { $_->[1] } @unsorted;

虽然在小情况下不太可能注意到开销,但对于更复杂的函数,O(n log n) 键提取成本会变得更高,并且最好只提取每个值的“排序键”一次,即nsort_by 做了什么。

【讨论】:

    猜你喜欢
    • 2014-09-21
    • 2011-12-17
    • 1970-01-01
    • 2019-12-26
    • 1970-01-01
    • 1970-01-01
    • 2014-06-07
    • 1970-01-01
    相关资源
    最近更新 更多