Perl 6 - stackoverflow(2017.1.1)

我想匹配任意一组单词,但是失败了,请问怎样才能正确地匹配到?

my @a=<a b c d e f>;
my $x="a1234567";
say $x ~~ m/ @a.any /;

Answer

my @a = <a b c d e f>;
my $x = "a1234567";
say $x ~~ /@a/

/@a//| @a/ 相同,它是最长的备选分支。对于备选分支,你可以使用 /|| @a/

sub foo($x) {
  $x**2
}

my $alist = (1,2, &foo ... ^ * > 100);

我想得到 (1 4 9 16 25 .. ) 而程序得到的是 (1 2 4 16 256)

Answer:

my @a = (1..*).map(* ** 2);  # using a Whatever-expression
my @a = (1..*).map(&foo);    # using your `foo` function

或者使用 Haskell/Python 那样的列表解析式:

my @a = ($_ ** 2 for 1..*);  # using an in-line expression
my @a = (foo $_ for 1..*);   # using your `foo` function

另外还有一种方法:

my @alist = {(++$)²} ... * > 70; # stop immediately after past 70
say @alist; # [1 4 9 16 25 36 49 64 81]

my @alist = {(++$)²} ...^ * > 70; # stop immediately before past 70
say @alist; # [1 4 9 16 25 36 49 64]

个人不推荐使用 $ 匿名变量的这种写法, 对于 new comer 不太友好。

Is it possible to use junction to match any of the values in a junction? I want to match any of the values in an array. What is the proper way to do it?

> my @a=<a b c>
[a b c]
> any(@a)
any(a, b, c)
> my $x=any(@a)
any(a, b, c)
> my $y = "a 1"
a 1
> say $y ~~ m/ $x /
False
> say $y ~~ m/ "$x" /
False
> my $x = any(@a).Str
any("a", "b", "c")
> say $y ~~ m/ $x /
False
> say $y ~~ m/ || $x /
False
> say $y ~~ m/ || @a /
「a」

Answer

junctions 不该被插值到正则表达式中。它们应该被用在普通的 Perl 6 表达式中,特别是带有比较操作符的表达式(例如 eq):

my @a = <x y z>;
say    "y" eq any(@a);  # any(False, True, False)
say so "y" eq any(@a);  # True

要在正则表达式中匹配一个数组的任意值,就在正则表达式中写上那个数组名好了(以@开头)。默认地,这被插值为 | 备选分支(“longest match”),但是你也可以把他指定为 || 备选分支(“first match”)。

my @a = <foo bar barkeep>;
say "barkeeper" ~~ / @a /;     # 「barkeep」
say "barkeeper" ~~ / || @a /;  # 「bar」

我需要排序数组的数组, .sort 方法能不能按照内层数组的不同索引来排序呢?

要排序的数组在一个更大的数组的外面:(birthday 是 ‘mmddyy’ 格式的:)

my @allRecords = [ [birthday1 firstName1 lastName1 [data1]
                   [birthday2 firstName2 lastName2 [data2] 
                   ...
                   [birthdayN firstNameN lastNameN [dataN] ];

@allRecords.sort by itself sorts by birthdays.

有什么好方法能按照 firstName 或 lastName 或 按照内层数组里面的数据来排序?

Answer

sort 方法接受一个可选的 sub 参数。如果元数是 1, 那么它使用返回值作为比较操作数;如果元数为 2, 那么你可以在两个元素之间手动作比较,两个元素的比较会返回 Less, Same, More

拿你上面的例子来说,我们可以像这样按照 first name 进行排序:

@allRecords.sort(*.[1])

我们可以先按照 last name 再按照 first name 进行排序,然后按照 birthday 来做单独的比较,就像这样:

@allRecords.sort(-> $a,$b {
    $a[2] cmp $b[2] || $a[1] cmp $b[1] || $a[0] cmp $b[0]
});

或者再次通过转换操作数:

@allRecords.sort(*.[2...0]);

变换 birthday 条目以至于我们能先按照 year 排序作为练习留给读者完成,但是其中一种方法是在合适的地方添加像这样的代码:

.comb(2).list.rotate(-1).join

你可以按照 lastname,firstname, birthday 这样的顺序排序:

@a.sort: *[2...0]

还有两个问题:

  • *.[1]*[1] 有什么区别?

两者没有任何区别,但是前者可读性更好!

  • range 操作符和 … 序列操作符有什么区别

range 不能倒数, ... 可以倒数。

在 Perl 6 中怎样找出列表中最大值的索引?

Answer

my @list = 1,2,9,6,9,5;
@list.maxpairs; # [2 => 9 4 => 9]

@list.maxpairs 用于获取索引和对应最大值的所有对儿。
@list.pairs.max(*.value).key 用于仅获取单个索引。

> @list.pairs.max(*.value).key
2

如何彻底地展平 Perl 6 的列表?这个问题不同于 How do I “flatten” a list of lists in perl 6?, 后者不是彻底的 flat。

my @a  = 'a', ('b', 'c' );
my @b  = ('d',), 'e', 'f', @a;
my @c  = 'x', $( 'y', 'z' ), 'w';

my @ab = @a, @b, @c;
say "ab: ", @ab;

my @f = @ab;

@f = gather {
    while @f {
        @f[0].elems == 1 ??
            take @f.shift.Slip
                !!
            @f.unshift( @f.shift.Slip )
        }
    }

say "f: ", @f;

这打印出:

ab: [[a (b c)] [(d) e f [a (b c)]] [x (y z) w]]
f: [a b c d e f a b c x y z w]

但这不够简洁。一种可行的办法是使用:gather/take/deepmap:

say gather @ab.deepmap(*.take)

postcircumfix [] 操作符可用于多维下标来获取一组展平的叶子节点,直到特定的深度,尽管 “无限深度” 版本还没有实现:

say @ab[*;*];     # (a (b c) (d) e f [a (b c)] x (y z) w)
say @ab[*;*;*];   # (a b c d e f a (b c) x y z w)
say @ab[*;*;*;*]; # (a b c d e f a b c x y z w)
say @ab[**];      # HyperWhatever in array index not yet implemented. Sorry.
  • 避免容器化 (containerization)

内置的 flat 函数能很好地展平深度嵌套的列表。问题是它不能落进 item 容器(Scalar)中。嵌套列表中非故意的 item 容器的常见来源有:

  • 数组(但不是列表)将其每个元素包装在一个新的 item 容器中,无论它之前有没有。
  • 如何避免:如果不需要 Array 提供的可变性,请使用列表的列表而不是数组的数组。使用绑定 := 可以用来代替赋值,将列表存储在@变量中,而不将其转换为数组
my @a  := 'a', ('b', 'c' );
my @b  := ('d',), 'e', 'f', @a;

say flat @b;  # (d e f a b c)
  • $variables 是 item 容器。
  • 如何避免:当将列表存储在 $ 变量中,然后将其作为元素插入到另一个列表中时,使用 <> 来对它进行 decontainerize(解容器化)。当把 $ 变量传递给 flat 时, 父列表的容器也可以使用 | 绕过:
my $a = (3, 4, 5);
my $b = (1, 2, $a<>, 6);

say flat |$b;  # (1 2 3 4 5 6)

未完待续。。。

    原文作者:焉知非鱼
    原文地址: https://www.jianshu.com/p/14bfcad35f40
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞