加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

perl6 – 创建任意分组的子列表

发布时间:2020-12-16 06:07:03 所属栏目:大数据 来源:网络整理
导读:我正在尝试根据每个字符串的第一部分(即,如果有选项卡,则在第一个选项卡之前的部分或如果没有选项卡的整个字符串)对字符串列表中的多个项目进行分组. 这有效: use Test;my @lines = "AtFoo","AtBar","B","AtBaz","B" ;my @expected = ["AtFoo","AtBar"
我正在尝试根据每个字符串的第一部分(即,如果有选项卡,则在第一个选项卡之前的部分或如果没有选项卡的整个字符串)对字符串列表中的多个项目进行分组.

这有效:

use Test;

my @lines    = "AtFoo","AtBar","B","AtBaz","B"
             ;

my @expected = ["AtFoo","AtBar"],["B","B"],["AtBaz"],["B"]
             ;

my @result = group-lines(@lines);

is @result,@expected,"Grouped correctly";

sub group-lines (@records) {
    my @groups;
    my @current-records;

    my $last-type;
    for @records -> $record {

        my $type = $record.split("t")[0];

        once { $last-type = $type }

        if $type ne $last-type {
            @groups.push: [@current-records];
            @current-records = ();
        }
        @current-records.push: $record;

        LAST { @groups.push: [@current-records] }
    }

    return @groups;
}

但它似乎很冗长.在Perl 6中没有更短的方法吗?请注意,我只想将类似于原始列表的连续成员的项目分组.

(更新)组内的顺序很重要.

UPDATE

这是一个更加数字化的例子.它根据后续数字与第一个数字的可分性对数字进行分组.

#!/bin/env perl6
use Test;

my @numbers = 2,4,6,3,9,12,14;

my @expected = [2,6],[3,12],[14];

my @result = group-nums(@numbers);

is @result,"Grouped correctly";

sub group-nums (@numbers) {
    my @groups;
    my @current-group;

    my $denominator = @numbers[0];

    for @numbers -> $num {

        if $num % $denominator {
            @groups.push: [@current-group];
            @current-group = ();
        }
        @current-group.push: $num;

    }
    @groups.push: [@current-group];

    return @groups;
}

解决方法

这是一个功能灵感的解决方案,虽然可能有点复杂:

use Test;

my @lines    = "AtFoo",["B"]
             ;

my @eq = @lines.map(*.split("t")[0]).rotor(2 => -1).map({ [eq] .list});
my @result = [@lines[0],],;
for @lines[1..*] Z @eq -> ($line,$eq) {
    @result.push([]) unless $eq;
    @result[*-1].push: $line;
}

plan 1;
is-deeply @result,@expected;

这个想法是@eq包含每个位置(第一个除外)如果前一个元素与当前元素具有相同的前缀,则为真.

但是我们并没有假装Lisp是唯一真神,而car和cdr是她的先知,我们可以简单地通过使用数组索引在我们需要时访问前一个元素来内联该决定:

my @result;
for @lines.kv ->  $idx,$elem {
    @result.push([]) if $idx == 0 || $elem.split("t")[0] ne @lines[$idx-1].split("t")[0];
    @result[*-1].push: $elem;
}

plan 1;
is-deeply @result,@expected;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读