如何按字母数字字符串中的数字排序? [英] How to sort by numbers in alpha numeric string?

查看:521
本文介绍了如何按字母数字字符串中的数字排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我使用以下格式的字符串数组:

[1900] ABC 15

如何使用perl sort对数组进行排序,以便按第一个数字排序,然后按第二个数字排序?

此示例来自 perldoc排序似乎是相关的:

my @new = sort {
    ($b =~ /=(\d+)/)[0] <=> ($a =~ /=(\d+)/)[0]
                        ||
                fc($a)  cmp  fc($b)
} @old;

解决方案

从文档中提取的示例显示了这一想法:按一个条件进行比较,以及如果通过cmp<=>发现它们相等,则 Schwartzian变换.

但是请记住,此类优化仅在较大的数据集上可证明,对于简单计算而言,其开销也是如此. 上面的基本sort通常就足够了.


根据要求讨论了问题" using perl sort ",我想补充一下,还有一些专门为此目的编写的模块,即自然排序",因为它们叫它.

具有 Sort :: Key :: Natural

的示例>

use warnings;
use strict;
use feature 'say';

use Sort::Key::Natural qw(natsort);

my @strings = qw(
    19_b_2
    13_z_7
    13_b_7
    20_a_1 
    13_b_5 
);

say for natsort @strings;

打印

13_b_5
13_b_7
13_z_7
19_b_2
20_a_1

这首先对数字部分进行排序,然后对字母进行排序.不需要第二种,上面的sort也不做.但是该手动排序很容易用标准进行修改,而好的模块当然不能灵活(不能删除字母排序).


注意 [0-9]\d匹配,但是其他字符(我被告知多了360个字符)也可以识别Unicode.从5.14开始可用的/a 字符集修饰符并非如此.但这具有比仅限制\d更广泛的作用.在 perlre 中搜索/a. 因此,在这里我将0-9用于精度和少量效率,而没有限制\s\w和POSIX字符类.

If I have an array of strings with the following format:

[1900] ABC 15

How can I sort the array using perl sort so that it sorts by the first number, then by the second?

This example from perldoc sort seems to be relevant:

my @new = sort {
    ($b =~ /=(\d+)/)[0] <=> ($a =~ /=(\d+)/)[0]
                        ||
                fc($a)  cmp  fc($b)
} @old;

解决方案

The example pulled from docs shows the idea: Compare by one criterion and if they are found equal by the cmp or <=> equality operators, which then return 0, go to the next criterion.

So in this case compare by the first number in the string, then by the second.

use warnings;
use strict;
use feature 'say';

my @old = ('[1900] ABC 15', '[1900] ABC 5', '[1800] ABC 20'); 

my @new = sort { 
    my ($a1, $a2) = $a =~ /([0-9]+)/g;
    my ($b1, $b2) = $b =~ /([0-9]+)/g;

    $a1 <=> $b1  or $a2 <=> $b2;

} @old;

say for @new;

prints

[1800] ABC 20
[1900] ABC 5
[1900] ABC 15

If the sort needs to be in the descending order swap a and b in comparisons.

This can be done more efficiently, in the first place by pre-computing the regexes for the whole list so that they aren't re-done every time an element is compared. The continuation of the example from docs shows this, the last version being the Schwartzian transform.

But recall that such optimizations are demonstrable only for larger data sets, and that for simple calculations their overhead counts, too. The above basic sort generally suffices.


Having discussed the problem "using perl sort", as asked for, I'd like to add that there are also modules written precisely for this purpose, "natural sorting," as they call it.

An example with Sort::Key::Natural

use warnings;
use strict;
use feature 'say';

use Sort::Key::Natural qw(natsort);

my @strings = qw(
    19_b_2
    13_z_7
    13_b_7
    20_a_1 
    13_b_5 
);

say for natsort @strings;

Prints

13_b_5
13_b_7
13_z_7
19_b_2
20_a_1

This sorts on numerical parts first, and then alphabetically. That second sort wasn't asked for and the sort above doesn't do it. But that manual sort can easily be amended with criterion while the nice module of course can't be as flexible (can't drop the alphabetical sort).


Note   A [0-9] is matched by \d but so are other characters (360 more I'm told), it being Unicode aware. This isn't the case with /a character set modifier, available since 5.14. But that has an effect broader than restricting just \d. Search for /a in perlre. Thus here I used 0-9 for precision and a small measure of efficiency, and without restricting \s, \w and POSIX character classes.

这篇关于如何按字母数字字符串中的数字排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆