Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > рекурся навеврное


Автор: Paul56 4.11.2008, 14:54
коллеги, объесните начинающему.
Читая книгу Лари решил попрактиковаться над много уровневыми вложениями.
предположим есть  меня текстовый файл.

в нём соответственной следующее

1|0|Shire
2|1|Frodo
3|1|Bagins
4|0|Allcreatures
5|4|Goblin
6|0|Oko
7|6|Saruman
8|7|Goblin1
9|7|Goblin1
10|7|Goblin1
11|7|Goblin1
12|11|Goblin2
13|8|Goblin2

Код

use strict;
use warnings;
open (FILE, "base.txt") or die $!;

my $i=0;
my @All_Line = ();
my (@id, @parentid, @name);
while (<FILE>) {
    chomp;
    ($id[$i], $parentid[$i], $name[$i]) = split (/\|/, $_);
    $i++;
}
close (FILE);
# Это так я решил прочитать данные из файла и занести каждую строчку в массивы
# а как дальше выполнить проверку что под чем находится ?

&proverka (0,0,$name[0]);

sub proverka {
    my $subid = shift;
    my $subpid = shift;
    my $subname = shift;
    foreach my $row (@id) {
        print '--',"$subname\n" if ($subpid == $subid);;
        &proverka($row,$parentid[$row],$name[$row]);
    }
}



что то я понять не могу что куда передовать чтобы обход выполнить?

p.s прошу не пинать, а лучше помочь советом как правильно это делается, очень хочется разобраться в мелочах.


Автор: IceSunrise 4.11.2008, 15:16
Paul56, а что значит "проверка"? Ты хочешь теперь посмотреть, у кого какие потомки? Т.е. например для первой записи:
ID=1; NAME=Shire; Childs: Frodo, Bagins.
Или какой результат должна дать проверка и что ты хочешь проверить?

Автор: Paul56 4.11.2008, 15:27
да совершенно верно

Автор: IceSunrise 4.11.2008, 15:52
Ну тогда я бы сделал так:

Код

use strict;
use warnings;
open (FILE, "base.txt") or die $!;

my %heros;
while (<FILE>)
{
    chomp;
    my ($id, $p_id, $name) = split (/\|/, $_);

    unless (exists $heros{$id})  # можно убрать проверку, если записи не повторяются
    {
        $heros{$id} = {name => $name, childs => []};

        if ($p_id != 0 and ! exists $heros{$p_id})  # родитель уже должен был встретиться
        {
           die "Unknown parent!\n";
        }
        else
        {
           push @{$heros{$p_id}->{childs}}, $id;  # сохраняем себя в качестве потомка
        }
     }
}
close (FILE);

foreach my $hero_id (keys %heros)
{
   print "ID=$hero_id; NAME=$heros{$hero_id}->{name}; CHILDS: ";
   foreach my $child_id (@{$heros{$hero_id}->{childs}})
   {
      print "$heros{$child_id}->{name} ";
   }
   print "\n";
}




Что-то вроде этого. Могут быть ошибки, не запускал, но идея должна быть понятна: каждый герой регистрируется в хеше по его id, в качестве значения этого хеша выступает указатель на другой хеш из двух элементов name - имя героя и childs - потомки героя.

Кстати, компактнее потомков можно выводить так:
print "ID=$hero_id; NAME=$heros{$hero_id}->{name}; CHILDS: ", map {$heros{$_}->{name}} @{$heros{$hero_id}->{childs}}, "\n";

Автор: gcc 4.11.2008, 16:08
(я бы попробовал хэш массивов...
или нет?  )

Paul56, используйте СУБД...

Автор: Paul56 4.11.2008, 16:45
Совершенно верно, этот пример я хотел реализовать к СУБД.

Автор: tolkien 5.11.2008, 08:35
Paul56
В вашем примере от рекурсии только одно название.

Вот настоящая рекурсия

Код

my @id = ('1|0|Shire',
'2|1|Frodo',
'3|1|Bagins',
'4|0|Allcreatures',
'5|4|Goblin',
'6|0|Oko',
'7|6|Saruman',
'8|7|Goblin1',
'9|7|Goblin1',
'10|7|Goblin1',
'11|7|Goblin1',
'12|11|Goblin2',
'13|8|Goblin2');

proverka(0, -1);
  
sub proverka
{
  my ($i, $_subid) = @_;
  return $i if ($i >= @id);
  my ($subid, $subpid, $subname) = split(/\|/, $id[$i], 3);
  
  if ($_subid == $subpid)
  {
     print $subname,' ';
  }
  elsif ($_subid == -1)
  {
    $_subid = $subid;
    print $subname,'--';
    proverka(0, $_subid);
    print "\n";
    $_subid = -1;
  }
  
  proverka($i + 1, $_subid);
}


Вывод
Код

Shire--Frodo Bagins 
Frodo--
Bagins--
Allcreatures--Goblin 
Goblin--
Oko--Saruman 
Saruman--Goblin1 Goblin1 Goblin1 Goblin1 
Goblin1--Goblin2 
Goblin1--
Goblin1--
Goblin1--Goblin2 
Goblin2--
Goblin2--

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)