2013-05-25 3 views
1

Я пытаюсь написать функцию Perl, которая принимает два списка/массивы и вычисляет их кросс-произведение (декартово произведение). В настоящее время у меня работает код, который принимает два входных списка и вычисляет кросс-продукт, но у меня проблема с печатью вложенных списков.Печать вложенного списка с форматированием

Я ищу совет по best способ печати вложенного списка. Вот моя текущая попытка, которая работает:

for(@C) { 
    for(@$_) { 
     print $_; 
    } 
    print " "; 
} 

# prints 
# 1A 1B 1C 1D 1E 1F 1G 1H 1I 
# 2A 2B 2C 2D 2E 2F 2G 2H 2I 
# 3A 3B 3C 3D 3E 3F 3G 3H 3I 
# 4A 4B 4C 4D 4E 4F 4G 4H 4I 
# etc ... 

, но это не выглядело Perly достаточно для меня. Так что я сделал еще одну попытку с map:

print map { 
    map { $_ } @$_; 
} @C; 

# prints 
# 1A1B1C1D1E1F1G1H1I 
# 2A2B2C2D2E2F2G2H2I 
# 3A3B3C3D3E3F3G3H3I 
# 4A4B4C4D4E4F4G4H4I 
# etc ... 

но детали все прижаты друг к другу. Нужно ли форматировать этот подход с map? Есть ли лучшие способы достижения этого?

Полный код функции:

use strict; 
use warnings; 

# globals 
my @digits = (1,2,3,4,5,6,7,8,9); 
my @letters = ("A","B","C","D","E","F","G","H","I"); 
my @rows = @digits; 
my @cols = @letters; 
my @squares = cross(\@rows, \@cols); 

sub cross { 
    my @C = []; 

    foreach (reverse @_) { 
     my @A = @$_; 

     @C = map { my $n = $_; map { [ $n, @$_ ] } @C } @A; 
    } 

    # works 
    #for(@C) { 
    # for(@$_) { 
    #  print $_; 
    # } 
    # print " "; 
    #} 

    print map { 
     map { $_ } @$_; 
    } @C; 

    return @C; 
} 
+0

почему 'отображение {$ _} @ $ _'? Как это иначе, чем просто '@ $ _'? – Flimzy

+0

@Flimzy '@ $ _' - это ссылка на массив, я хочу видеть отдельные элементы. –

+0

Почему нижний предел для этого вопроса? –

ответ

3
print map { join '', @$_, ' ' } @C; 
+0

Это именно то, что я искал. Благодаря! –

3

Там нет ничего, что говорит map не может вернуть отформатированные строки:

print map { " $_" }; 

Или для более точного контроля, использование присоединиться:

print join ' ', map { ... }; 
0

По умолчанию массивы интерполируются в строки, как вы хотите их здесь. Так что:

#! /usr/bin/env perl 
use common::sense; 

my @a = ([qw/1A 1B 1C 1D 1E 1F 1G 1H 1I/], 
     [qw/2A 2B 2C 2D 2E 2F 2G 2H 2I/], 
     [qw/3A 3B 3C 3D 3E 3F 3G 3H 3I/], 
     [qw/4A 4B 4C 4D 4E 4F 4G 4H 4I/], 
     ['etc', '...']); 

say "# prints"; 
say "# @$_" for @a; 

Выходы:

# prints 
# 1A 1B 1C 1D 1E 1F 1G 1H 1I 
# 2A 2B 2C 2D 2E 2F 2G 2H 2I 
# 3A 3B 3C 3D 3E 3F 3G 3H 3I 
# 4A 4B 4C 4D 4E 4F 4G 4H 4I 
# etc ... 

В качестве альтернативы,

local $" = ', '; 
say "# @$_" for @a; 

Выходы:

# 1A, 1B, 1C, 1D, 1E, 1F, 1G, 1H, 1I 
# 2A, 2B, 2C, 2D, 2E, 2F, 2G, 2H, 2I 
# 3A, 3B, 3C, 3D, 3E, 3F, 3G, 3H, 3I 
# 4A, 4B, 4C, 4D, 4E, 4F, 4G, 4H, 4I 
# etc, ... 
+0

Спасибо за это. Однако я не был жестко кодировал строки, я принимал '(1,2,3,4,5,6,7,8,9)' и '(A, B, C, D, E, F, G, H, I) 'и вычисляя декартово произведение, чтобы получить все остальные строки. –

+0

Не могли бы вы объяснить, что делает первый блок кода, который вы присваиваете '@ a'? –

+0

@HunterMcMillen, '([qw/a b c /], [qw/1 2 3 /])' - список arrayrefs. Это эквивалентно '(['a', 'b', 'c'], [1, 2, 3])', а присвоение этого значения @a эквивалентно: 'my @a; $ a [0] [0] = 'a'; $ a [0] [1] = 'b'; ...; $ a [1] [2] = 3; ' –

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