List 转换一个单词';用Raku将字符简明地输入其ascii代码列表

List 转换一个单词';用Raku将字符简明地输入其ascii代码列表,list,raku,List,Raku,我正在尝试将单词wall转换为其ascii代码列表(119、97、108、108),如下所示: my @ascii="abcdefghijklmnopqrstuvwxyz"; my @tmp; map { push @tmp, $_.ord if $_.ord == @ascii.comb.any.ord }, "wall".comb; say @tmp; 有没有一种方法可以使用@tmp而不在单独的行中声明它 有没有办法在一行而不是三行中生成asci

我正在尝试将单词wall转换为其ascii代码列表
(119、97、108、108)
,如下所示:

my @ascii="abcdefghijklmnopqrstuvwxyz";

my @tmp;
map { push @tmp, $_.ord if $_.ord == @ascii.comb.any.ord }, "wall".comb;
say @tmp;
  • 有没有一种方法可以使用
    @tmp
    而不在单独的行中声明它

  • 有没有办法在一行而不是三行中生成ascii代码列表?如果是,怎么做


  • 请注意,我必须使用
    @ascii
    变量,也就是说,我不能使用连续递增的ascii序列
    (97、98、99…122)
    ,因为我计划将此代码也用于非ascii语言。

    在这里我们可以做一些事情来使其工作

    首先,让我们处理
    @ascii
    变量。
    @
    符号表示位置变量,但您为其指定了一个字符串。这将创建一个1元素数组
    ['abc…']
    ,这将导致以后的问题。根据需要的通用性,我建议直接创建阵列:

    my @ascii = <a b c d e f g h i j k l m n o p q r s t u v x y z>;
    my @ascii = 'a' .. 'z';
    my @ascii = 'abcdefghijklmnopqrstuvwxyz'.comb;
    
    在这里,我使用了
    $
    符号,因为
    any
    确实指定了任何单个值,因此它的功能也是如此(这也让我们的生活更轻松)。我个人会使用
    $ascii
    ,但我会使用一个单独的名称,以使后面的示例更易于区分

    现在我们可以处理map函数了。基于上述两个版本的ascii,我们可以将map函数重写为以下任意一种

    { push @tmp, $_.ord if $_ eq @ascii.any  }
    { push @tmp, $_.ord if $_ eq $ascii-char }
    
    请注意,如果您喜欢使用
    ==
    ,您可以继续在初始
    ascii
    创建中创建数值,然后使用
    $.ord
    。此外,就我个人而言,我喜欢命名映射变量,例如:

    { push @tmp, $^char.ord if $^char eq @ascii.any  }
    { push @tmp, $^char.ord if $^char eq $ascii-char }
    
    其中,
    $^foo
    替换了
    $
    (如果您使用了多个,它们会将字母顺序映射到
    @[0]
    @[1]
    ,等等)

    但让我们来看一个更有趣的问题。我们怎样才能做到这一切而不需要预先声明
    @tmp
    ?显然,这只需要在map循环中创建数组。当我们没有ASCII值时,您可能会认为这可能很棘手,但是
    if
    语句如果不运行,则返回
    空的
    (或
    ()
    )这一事实让生活变得非常简单:

    my @tmp = map { $^char.ord if $^char eq $ascii-char }, "wall".comb;
    my @tmp = map { $^char.ord if $^char eq @ascii.any  }, "wall".comb;
    

    如果我们使用“wáll”,则
    map
    收集的列表将是
    119,空,108,108
    ,自动返回为
    119,108,108
    。因此,
    @tmp
    被设置为仅
    119108108

    是的,有一种更简单的方法

    “wall.ords.grep('az'.ords.minmax));
    
    当然,这取决于
    a
    z
    是一个完整的序列。这是因为
    minmax
    基于列表中的最小值和最大值创建范围对象

    如果它们不是在一个完整的序列中,你可以使用一个连接

    “wall.ords.grep('az'.ords.minmax |'az'.ords.minmax);
    

    但是你说你想和其他语言相匹配。对我来说,这叫雷格克斯

    “wall.comb.grep(/^&$/).map(*.ord)
    
    这与同样使用ASCII的小写字母相匹配

    事实上,我们可以让它变得更简单
    comb
    可以接受一个正则表达式,该正则表达式确定从输入中提取哪些字符

    “墙”.comb(/&/).map(*.ord)
    # (119, 97, 108, 108)
    “ΔαβγΔε”.comb(/&/).map(*.ord)
    # (945, 946, 947, 948, 949)
    #不包括Γ或Δ,因为它们不是小写
    

    请注意,如果您没有组合重音,以上仅适用于ASCII

    “de\c[组合尖锐重音]f”。梳(/&/)
    #(“d”、“f”)
    
    组合锐音重音与
    e
    组合,构成带锐音的拉丁文小写字母e。 该组合字符不是ASCII格式,因此将跳过它

    如果角色没有一个组合值,它会变得更奇怪

    “f\c[组合急性重音]”.comb(/&/)
    #(“f́”,)
    
    这是因为
    f
    是小写的,并且是ASCII格式。不过,编写代码点会被带到车上

    基本上,如果您的数据有,或者可以有组合重音,并且如果它可以破坏东西,那么您最好在它仍然是二进制形式时处理它

    $buf.grep:{
    .uniprop()等式'Ll'#
    &&.uniprop('Block')eq“基本拉丁语”#ASCII
    }
    
    上述方法也适用于单字符字符串,因为
    .uniprop
    适用于表示码点的整数或实际字符

    “墙”。comb.grep:{
    .uniprop()等式'Ll'#
    &&.uniprop('Block')eq“基本拉丁语”#ASCII
    }
    
    请再次注意,这与编写代码点有相同的问题,因为它可以处理字符串


    您可能还想使用
    .uniprop('Script')
    而不是
    .uniprop('Block')
    ,具体取决于您想要执行的操作。

    以下是使用Raku的
    trans
    方法的工作方法(在Raku REPL中执行的代码片段):

    >my@a=“wall”.comb;
    [w a l]
    >@a.trans('abcdefghijklmnopqrstuvwxyz'=>ords('abcdefghijklmnopqrstuvwxyz')).put;
    119 97 108 108
    
    上面,我们处理一个ascii字符串。下面我添加了“é”字符,并展示了一个两步解决方案:

    >my@a=“wallé”.comb;
    [w a lé]
    >my@b=@a.trans('abcdefghijklmnopqrstuvxyz'=>ords('abcdefghijklmnopqrstuvxyz');
    [119 97 108 108 é]
    >@b.trans(“é”=>ords(“é”).put
    119 97 108 108 233
    
    注1:尽管上面所有的代码都很好,但当我尝试将字母表缩短为
    'a'..'z'
    时,我发现返回值错误…因此使用了完整的
    'abcdefghijklmnopqrstuvxyz'

    注2:我脑海中的一个问题是,当
    trans
    无法识别字符时,试图抑制输出(例如,如何抑制将“é”指定为最后一个元素)
    my @tmp = map { $^char.ord if $^char eq $ascii-char }, "wall".comb;
    my @tmp = map { $^char.ord if $^char eq @ascii.any  }, "wall".comb;