首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在给定位置拆分字符串

在给定位置拆分字符串
EN

Stack Overflow用户
提问于 2020-01-23 01:06:47
回答 4查看 174关注 0票数 9

如何很好地/惯常地在位置列表上拆分字符串?

我所拥有的:

代码语言:javascript
复制
.say for split-at( "0019ABX26002", (3, 4, 8) ); 

sub split-at( $s, @positions )
{
  my $done = 0;

  gather 
  {
    for @positions -> $p
    {
      take $s.substr($done, $p - $done );
      $done = $p;
    }
    take $s.substr( $done, * );
  }
}

这是合理的。然而,我对此缺乏语言支持感到困惑。如果"split on“是一个东西,为什么"split at”不也是呢?我认为这应该是一个核心操作。我应该会写

代码语言:javascript
复制
.say for "0019ABX26002".split( :at(3, 4, 8) );

或者也许我忽略了什么?

编辑:我们到目前为止的一些基准测试

代码语言:javascript
复制
O------------O---------O------------O--------O-------O-------O
|            | Rate    | array-push | holli  | raiph | simon |
O============O=========O============O========O=======O=======O
| array-push | 15907/s | --         | -59%   | -100% | -91%  |
| holli      | 9858/s  | 142%       | --     | -100% | -79%  |
| raiph      | 72.8/s  | 50185%     | 20720% | --    | 4335% |
| simon      | 2901/s  | 1034%      | 369%   | -98%  | --    |
O------------O---------O------------O--------O-------O-------O

代码:

代码语言:javascript
复制
use Bench;

my $s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccddddddddddddddddddddddddddddddddddddefggggggggggggggggggg";
my @p = 29, 65, 69, 105, 106, 107;

Bench.new.cmpthese(1000, {
  holli  => sub { my @ = holli($s, @p); },
  simon => sub { my @ = simon($s, @p); },
  raiph => sub { my @ = raiph($s, @p); },
  array-push => sub { my @ = array-push($s, @p); },
});

#say user($s, @p);


sub simon($str, *@idxs ) {
    my @rotors = @idxs.map( { state $l = 0; my $o = $_ - $l; $l = $_; $o } );
    $str.comb("").rotor( |@rotors,* ).map(*.join(""));
}

sub raiph($s, @p) {
    $s.split( / <?{$/.pos == any(@p)}> / )
}

sub holli( $s, @positions )
{
  my $done = 0;

  gather
  {
    for @positions -> $p
    {
      take $s.substr($done, $p - $done );
      $done = $p;
    }
    take $s.substr( $done, * );
  }
}

sub array-push( $s, @positions )
{
  my $done = 0;
  my @result;

  for @positions -> $p
  {
    @result.push: $s.substr($done, $p - $done );
    $done = $p;
  }
  @result.push: $s.substr( $done, * );

  @result;
}
EN

回答 4

Stack Overflow用户

发布于 2020-01-23 01:31:31

就我个人而言,我会将它拆分成一个列表,使用rotor将列表拆分并连接结果:

代码语言:javascript
复制
"0019ABX26002".comb().rotor(3,1,4,*).map(*.join)

如果您想要拆分at函数(使用给定的索引):

代码语言:javascript
复制
sub split-at( $str, *@idxs ) { 
    my @rotors = @idxs.map( { state $l = 0; my $o = $_ - $l; $l = $_; $o } );
    $str.comb("").rotor( |@rotors,* ).map(*.join("")); 
}

基本上,如果我想做list类型的东西,我会使用list。

从函数式编程的角度来看,我想出了另一个我非常喜欢的版本:

代码语言:javascript
复制
sub split-at( $str, *@idxs ) {
    (|@idxs, $str.codes)
    ==> map( { state $s = 0;my $e = $_ - $s;my $o = [$s,$e]; $s = $_; $o } )
    ==> map( { $str.substr(|$_) } );
}

结果是它比另一个稍微慢一点。

票数 9
EN

Stack Overflow用户

发布于 2020-01-23 01:26:17

一种方法:

代码语言:javascript
复制
.say for "0019ABX26002" .split: / <?{ $/.pos ∈ (3,4,8) }> /

显示:

代码语言:javascript
复制
001
9
ABX2
6002
票数 4
EN

Stack Overflow用户

发布于 2020-01-23 12:04:35

因为每个子字符串不依赖于另一个,所以hyper成为一种选择。

代码语言:javascript
复制
method split-at(\p) {
  do hyper for (0,|p) Z (|p,self.chars) {
    self.substr: .head, .tail - .head
  }
}

或以子形式:

代码语言:javascript
复制
sub split-at(\s, \p) {
  do hyper for (0,|p) Z (|p,s.chars) {
    s.substr: .head, .tail - .head
  }
}

但是所涉及的开销是不值得的,除非所请求的元素的数量是极端的- in我的测试它大约比天真的形式慢十倍。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59864867

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档