我是学习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
答案 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]+)
对于每个所需结果,它都有三个捕获组。您可以根据需要为其添加或减少边界,它可能比其他方法更快。
此图显示了表达式的工作方式,您可以在此link中可视化其他表达式:
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);
您可以简单地使用$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
是破坏性的。