2013-07-09 2 views
1

У меня есть массив массив, который выглядит следующим образом -удалить массив из АОА Perl

$VAR1 = [ 
      'sid_R.ba', 
      'PS20TGB2YM13', 
      'SID_r.BA', 
      'ARS', 
      'XBUE' 
     ]; $VAR2 = [ 
      'sddff.pk', 
      'PQ10XD06K800', 
      'SDDFF.PK', 
      'USD', 
      'PINX' 
     ]; $VAR3 = [ 
      'NULL', 
      'NULL', 
      'NULL', 
      '.', 
      'XNAS' 
     ]; $VAR4 = [ 
      'NULL', 
      'NULL', 
      'NULL', 
      '.', 
      'XNAS' 
     ]; $VAR5 = [ 
      'NULL', 
      'NULL', 
      'NULL', 
      'EUR', 
      'OTCX' 
     ]; $VAR6 = [ 
      'sid.ba', 
      'PS20TGB1TN17', 
      'SID.BA', 
      'ARS', 
      'XBUE' 
     ]; 

Я хочу, чтобы удалить весь блок (массив реф), если какой-либо из его элементов является NULL

I есть код, в котором массив генерируется, поэтому я попробовал цикл for для удаления, но затем индекс массива уменьшается внутри цикла for.

Так что я не знаю, в каком порядке будет массив или длина массива. Пожалуйста, мне нужно общее решение.

Пожалуйста, помогите.

Благодаря

ответ

7

Вы, кажется, есть массив как

my @AoA = (
    [1, 2, 3], 
    [4, 5, 6], 
    [7, 8, "NULL"], 
    [9, 10], 
); 

Вы хотите выбрать все дочерние массивы, которые не содержат "NULL". Легко: Просто использовать вложенные grep:

my @AoA_sans_NULL = grep { 
    not grep { $_ eq "NULL" } @$_ 
} @AoA; 

grep { CONDITION } @array выбирает все элементы из @array где CONDITION оценивается как истина.

grep { $_ eq "NULL" } @$_ подсчитывает количество "NULL" s во внутреннем массиве. Если это равно нулю, наше условие истинно, иначе мы не хотим поддерживать этот подматрица.

+0

Мы пришли в основном к тому же решению, хотя вы сделали гораздо лучшую работу по распаковке и объяснению этого. –

+0

+1, очень элегантный –

+0

спасибо мужчина !! действительно оценили. – Gaurav

2

Это делает то, что вы хотите?

my @new_array = grep { scalar(grep { $_ eq 'NULL' } @{$_}) == 0 } @old_array; 
5
use List::MoreUtils qw(none); 
    my @filtered = grep { 
     none { $_ eq "NULL" } @$_; 
    } @array; 
+0

Ваш 'не любой ...' может быть записан 'none {$ _ eq" NULL "} @ $ _' – amon

+0

@amon tnx ........ –

+0

Теперь это (IMHO) самый perlish, и вероятно, наиболее эффективное решение. – amon

0

Старая школа:

my @filtered =(); 

ARRAY_LOOP: 
for my $array (@AoA){ 

    ITEM_LOOP: 
    for my $item (@$array){ 

    next ARRAY_LOOP if $item eq 'NULL'; 

    } # end ITEM_LOOP 

    push @filtered, $array; 

} # end ARRAY_LOOP 
0

Этот код будет медленнее, чем другие, но решение на месте может оказаться полезным, если данные посаженные очень велико.

use List::MoreUtils qw(any); 
for(my $i = 0; $i < @AoA; $i ++) { 
    splice @AoA, $i --, 1 
     if any { $_ eq "NULL" } @{ $AoA[$i] }; 
} 
0

не- grep из grep решения:

my @array = ...; #Array of Arrays 
for my $array_index (reverse 0 .. $#array) { 
    my @inner_array = @{ $array[$array_index] }; 
    if (grep /^NULL$/, @inner_array) { 
     splice @array, $array_index, 1; 
    } 
} 
say Dumper @array; 

Команда splice удаляет всю подмассив. Мне не нужно создавать @inner_array Я мог бы использовать мой разыменованный @{ $array[$array_index] } в выражении if, но мне нравится идти для ясности.

Единственное, что вы получили, - это пройти через массив массивов назад. Если вы пройдете через свой массив от первого элемента до последнего элемента, вы удалите элемент 2, который приведет к уменьшению индексов всех остальных элементов. Если я сначала удалю элемент 4, то элементы с 0 по 3 не изменят свой индекс.

Это не так элегантный как grep в течение grep решений, но это намного проще в обслуживании. Представьте себе человека, который должен пройти через вашу программу через шесть месяцев с этого момента, пытаясь выяснить, что:

grep { not grep { $_ eq "NULL" } @$_ } @array; 

делает.

Смежные вопросы