如何在Perl中将数组值拆分为新的单独数组?

时间:2019-05-09 06:23:44

标签: arrays regex perl split push

我是学习Perl的初学者。 我在这里尝试做的是拆分数组@value并将其插入新数组。我的问题是,我不完全知道如何使我的代码循环运行并获得所需的结果。

是否可以使用这种方法获得所需的结果,或者是否有其他替代方法获得相同的结果?

我的代码如下;

my @separated = ();
my @separated1 = ();
my @separated2 = ();
my @separated3 = ();
my $counter = 0;
my @values = "aaa 111 AAA bbb 222 BBB ccc 333 CCC ddd 444 DDD";

foreach (@values) {
my @separated = split(' ', $_);
push @separated1, $separated[0];
push @separated2, $separated[1];
push @separated3, $separated[2];
}
$counter++

print "separated1 = @separated1\n";
print "separated2 = @separated2\n";
print "separated3 = @separated3\n";

我得到的结果;

  

separated1 = aaa

     

separated2 = 111

     

separated3 = AAA

所需结果;

  

separated1 = aaa bbb ccc ddd

     

separated2 = 111222333444

     

分隔3 = AAA BB CCC DD

6 个答案:

答案 0 :(得分:4)

 <input type="text" matInput [formControl]="formControl" [matAutocomplete]="auto">
 <mat-autocomplete #auto="matAutocomplete" [displayWith]="inputDisplay" (optionSelected)='onSelectItem($event.option.value)'>
    <mat-option *ngFor="let item of filteredItems | async" [value]="item">
       <div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="20px">
         <div class="flags" [ngClass]="item.flagClass"></div>
         <span> {{ item.countryName }} </span>
       </div>
    </mat-option>
  </mat-autocomplete>

上面的内容也可以写成如下:

inputDisplay(item?: Country): string | undefined {
   const htmlReturned = '<div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="20px">' +
                  '<div class="flags item.flagClass"></div>' +
                  '<span> {{ item.countryName }} </span>' +
                  '</div>';

   return item ? htmlReturned : undefined;
}

您确定要并行数组吗?尽管它们可以节省内存,但通常很难与它们一起使用,并且更容易出错。在对象占主导的景观中,它们几乎是看不到的。

您可以使用AoA:

my ( @foos, @bars, @quxs );
my @values = split(' ', $input);
while (@values) {
   push @foos, shift(@values);
   push @bars, shift(@values);
   push @quxs, shift(@values);
}

您可以使用AoH:

my ( @foos, @bars, @quxs );
for ( my @values = split(' ', $input); @values; ) {
   push @foos, shift(@values);
   push @bars, shift(@values);
   push @quxs, shift(@values);
}

答案 1 :(得分:4)

C样式的for循环很适合在每个第3个元素上进行迭代的罕见情况

my $string = 'aaa 111 AAA bbb 222 BBB ccc 333 CCC ddd 444 DDD';

my (@sep1, @sep2, @sep3);

my @values = split ' ', $string;

for (my $i=0; $i <= $#values; $i += 3) {
    push @sep1, $values[$i];
    push @sep2, $values[$i+1];
    push @sep3, $values[$i+2];
}

这假定数组确实具有所有三元组,或者更好地检查每个元素。

但是,使用单个结构通常比使用一组并行数组要好得多。例如,使用具有数组引用元素的数组

use Data::Dump qw(dd);

my @sep;

for (my $i=0; $i <= $#values; $i += 3) { 
    for my $j (0..2) { 
        push @{$sep[$j]}, $values[$i+$j]; 
    }
}

dd \@sep;

可以通过更加简洁的方式避免重复迭代

for my $i (0..$#values) { 
    push @{$sep[$i%3]}, $values[$i] 
}

替换两个循环。

此打印

[
  ["aaa", "bbb", "ccc", "ddd"],
  [111, 222, 333, 444],
  ["AAA", "BBB", "CCC", "DDD"],
]

我使用Data::Dump查看复杂数据。核心中的替代方法是Data::Dumper


然后有很多模块带有各种用于处理列表的实用程序例程。

例如,使用part中的List::MoreUtils@values数组进行分区

my @sep = map { [ @values[@$_] ] } part { $_%3 } 0..$#values;

这与上面的arrayrefs产生相同的@sep

part返回一个数组引用列表,每个数组引用都包含索引,因为它对@values的索引列表进行了分区。然后在map中,将每个arrayref评估到其索引列表(@$_)中,该列表用于获取@values的对应切片;该列表用于使用[]进行arrayref。因此,map返回一个arrayrefs列表,并根据需要对值进行分区。

要使用参考,请参见教程perlreftut和参考perlref

答案 2 :(得分:2)

使用非核心但非常有用的List::MoreUtils模块中的part的另一个版本,它直接对元素进行分区:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say state/;
use List::MoreUtils qw/part/;

my $str = "aaa 111 AAA bbb 222 BBB ccc 333 CCC ddd 444 DDD";

my ($sep1, $sep2, $sep3) = part { state $i = 0; $i++ % 3 } split(' ', $str);

say "sep1: @$sep1";
say "sep2: @$sep2";
say "sep3: @$sep3";

打印出

sep1: aaa bbb ccc ddd
sep2: 111 222 333 444
sep3: AAA BBB CCC DDD

state是这里的魔力,它最终在其所在的块中创建了一个局部变量,该变量在该块的多次评估中保持其值。

答案 3 :(得分:2)

List::UtilsBy的另一项工作:

use strict;
use warnings;
use List::UtilsBy 'bundle_by', 'unzip_by';

my $string = 'aaa 111 AAA bbb 222 BBB ccc 333 CCC ddd 444 DDD';
my @vals = split ' ', $string;
my ($sep1, $sep2, $sep3) = unzip_by { @$_ } bundle_by { [@_] } 3, @vals;

print "sep1: @$sep1\nsep2: @$sep2\nsep3: @$sep3\n";

答案 4 :(得分:1)

This expression可能会帮助您获得所需的结果:

([a-z]+\s)([0-9]+\s)([A-Z]+)

对于每个所需结果,它都有三个捕获组。您可以根据需要为其添加或减少边界,它可能比其他方法更快。

enter image description here

此图显示了表达式的工作方式,您可以在此link中可视化其他表达式:

enter image description here

JavaScript测试

const regex = /([a-z]+\s)([0-9]+\s)([A-Z]+)/gm;
const str = `aaa 111 AAA bbb 222 BBB ccc 333 CCC ddd 444 DDD`;
const subst = `\n$1 & $2 & $3\n`;

// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);

console.log('Substitution result: ', result);

Perl测试

您可以简单地使用$1$2$3并分离数据:

use strict;

my $str = 'aaa 111 AAA bbb 222 BBB ccc 333 CCC ddd 444 DDD';
my $regex = qr/([a-z]+\s)([0-9]+\s)([A-Z]+)/mp;
my $subst = '';

my $result = $str =~ s/$regex/$subst/rg;

print "The result of the substitution is' $result\n";

性能测试

此JavaScript代码段使用简单的100万次for循环来显示该表达式的性能。

const repeat = 1000000;
const start = Date.now();

for (var i = repeat; i >= 0; i--) {
	const string = 'aaa 111 AAA bbb 222 BBB ccc 333 CCC ddd 444 DDD';
	const regex = /([a-z]+\s)([0-9]+\s)([A-Z]+)/gm;
	var match = string.replace(regex, "$1");
}

const end = Date.now() - start;
console.log("YAAAY! \"" + match + "\" is a match  ");
console.log(end / 1000 + " is the runtime of " + repeat + " times benchmark test.  ");

答案 5 :(得分:1)

我喜欢@ikegami和@zdim的解决方案。 @zdim对List::MoreUtils中的import numpy as np import matplotlib.pyplot as plt from mpl_toolkits import mplot3d from matplotlib import animation fig = plt.figure() ax = fig.add_subplot(111, projection='3d') X = np.linspace(-5,5,10) Y = np.linspace(-5,5,10) Z =(X+Y)*0 line, = ax.plot([], [], [], lw=2) def init(): line.set_data([], []) line.set_3d_properties([]) return line, def animate(i, line, X, Y, Z): line.set_data(X[:i], Y[:i]) line.set_3d_properties(Z[:i]) return line, anim = animation.FuncAnimation(fig, animate, init_func=init, fargs=(line, X, Y, Z),frames=10, interval=200,repeat_delay=5, blit=True) plt.show() 的使用使我想起part()

natatime

并不是真正的考虑因素,但可能是有趣的:通过使用临时数组(my @values = split(' ', "aaa 111 AAA bbb 222 BBB ccc 333 CCC ddd 444 DDD"); use List::MoreUtils 'natatime'; my $nata_iter = natatime 3, @values ; my @aoa ; while (my @tmp = $nata_iter->()) { push @aoa, \@tmp; }; )存储迭代器的输出,原始的@tmp保持不变,而更简单的@values是破坏性的。