我有一个类似
的数组@tmp = ('value1-1', 'value1-2', 'value1-3', '', 'value2-1', 'value2-2', 'value2-3')
在看到值为空''
后,如何将数组分成两部分?
这样输出应该是这样的
@value1=('value1-1','value1-2','value1-3');
@value2=('value2-1','value2-2','value2-3');
我试过这种方式
foreach $item(@tmp){
unless($add == ''){
#print $add;
push (@value,$add);
}
}
它不会返回任何内容。
答案 0 :(得分:6)
在使用数组引用时循环遍历列表,以确定要填充的目标数组。
my @value1;
my @value2;
my @tmp = ('value1-1', 'value1-2', 'value1-3', '', 'value2-1', 'value2-2', 'value2-3');
my $target = \@value1;
for my $val ( @tmp ) {
if ( $val eq '' ) {
$target = \@value2;
}
else {
push( @{$target}, $val );
}
}
答案 1 :(得分:3)
执行此操作的唯一方法是搜索第一个空白元素。您可以使用List::MoreUtils
中的firstidx
功能,方便地执行此操作
use strict;
use warnings;
use List::MoreUtils 'firstidx';
my @tmp = ('value1-1', 'value1-2', 'value1-3', '', 'value2-1', 'value2-2', 'value2-3');
my $i = firstidx { length == 0 } @tmp;
my @value2 = @tmp;
my @value1 = splice @value2, 0, $i;
shift @value2;
use Data::Dump;
dd \@value1, \@value2;
<强>输出强>
(
["value1-1", "value1-2", "value1-3"],
["value2-1", "value2-2", "value2-3"],
)
该模块不是核心模块,因此您可能不希望安装它。您可以使用
编写自己的辅助函数sub first_blank_idx {
my ($arr) = @_;
length $arr->[$_] or return $_ for 0 .. $#$arr;
return -1;
}
并将通话更改为firstidx
至my $i = first_blank_idx(\@tmp)
答案 2 :(得分:2)
use strict;
use warnings;
my @tmp = ('value1-1', 'value1-2', 'value1-3', '', 'value2-1', 'value2-2', 'value2-3');
my @blanks = grep {$tmp[$_] eq ''} 0 .. $#tmp;
die "No blank elements" unless @blanks;
warn "More than one blank" if @blanks > 1;
my @value1 = @tmp[0 .. $blanks[0]-1];
my @value2 = @tmp[$blank[0]+1 .. $#tmp];
use Data::Dump;
dd \@value1, \@value2;
答案 3 :(得分:2)
您可以使用List::MoreUtils中的part
对数组进行分区:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use List::MoreUtils qw(part);
my @array = (
'foo', 'bar', 'baz', '',
'alpha', 'beta', 'gamma', '',
'apple', 'pear', 'banana'
);
my $index = 1;
my @parts = part { $_ eq '' ? $index++ && 0 : $index } @array;
print Dumper \@parts;
$VAR1 = [
[
'',
''
],
[
'foo',
'bar',
'baz'
],
[
'alpha',
'beta',
'gamma'
],
[
'apple',
'pear',
'banana'
]
];
从示例中可以看出,这适用于任意数量的分区,而不仅仅是两个分区。结果存储在一个数组数组中,空记录(''
)存储在$array[0]
中。
答案 4 :(得分:1)
您可以使用split
和join
来做到这一点非常简洁:
use strict;
use warnings;
my @tmp =
('value1-1', 'value1-2', 'value1-3', '', 'value2-1', 'value2-2', 'value2-3');
# note that since the pivot value is empty there with be two && in its place
# we can split on that
my ($values1, $values2) =
map { [split '&', $_] } split('&&', join('&', @tmp));
__END__
[
'value1-1',
'value1-2',
'value1-3'
],
[
'value2-1',
'value2-2',
'value2-3'
]
答案 5 :(得分:1)
正如 Andy Lester 在他的评论中指出的那样,除非数组很大,否则原始@tmp
数组的逐项过滤可能足够快。
如果Perl 5安装版本为14或更高版本,则push
接受数组引用作为其第一个参数,因此可以使用像这样的状态变量整齐地编写数组之间的切换
use strict;
use warnings;
use 5.014;
my @tmp = ('value1-1', 'value1-2', 'value1-3', '', 'value2-1', 'value2-2', 'value2-3');
my (@value1, @value2);
my $split;
for (@tmp) {
if (length or $split) {
push $split ? \@value2 : \@value1, $_;
}
else {
$split = 1;
}
}
use Data::Dump;
dd \(@value1, @value2);
<强>输出强>
(
["value1-1", "value1-2", "value1-3"],
["value2-1", "value2-2", "value2-3"],
)
在早期版本中,必须取消引用该数组,因此push
调用将变为
push @{ $split ? \@value2 : \@value1 }, $_;