Forum Webscript.Ru

Программирование => Perl => Тема начата: cr4ck3r от 21 Апреля 2005, 11:00:27

Название: Сравнить два массива
Отправлено: cr4ck3r от 21 Апреля 2005, 11:00:27
Что-то я туплю немного. Подскажите как наиболее эффективно решить такую задачу:

Имеется массив со списком имен файлов. Имеется текстовый файл, также со списком имен файлов. Требуется, из массива удалить имена файлов которые встречаются в текстовом файле, и получить в результате список файлов которые не упоминаются в текстовом файле. Что-то я никак не могу найти нужного решения, а точнее наиболее эффективного и быстрого.
Название: Сравнить два массива
Отправлено: commander от 21 Апреля 2005, 11:14:55
cr4ck3r
за тебя весь код написать? приведи хоть код своего, как ты считаешь, не эфективного решения... посмотрим если надо оптимизуруем...
Название: Сравнить два массива
Отправлено: cr4ck3r от 21 Апреля 2005, 11:20:35
Сори. Забыл.
Код в общем-то еще в очеь черновом варианте, поэтому не пугайтесь некоторых конструкций - они для дебаггинга.
В общем-то тут наверно стоит привести две функции:

sub GetFiles {
my $month=shift;
GetError("Can\'t find downloads directory by path: $CONFIG{\'path\'}") unless(-d $CONFIG{\'path\'});
my $mnum=MonName($month);
my $year=substr($CONFIG{\'year\'},2,2);
$mnum=$year . $mnum;
opendir(DIR,$CONFIG{\'path\'}) || GetError("Can\'t open downloads directory: $!");
my @FILES=grep(!/^\\.\\.?$/,readdir DIR);
@FILES=grep(/^$mnum/,@FILES);
close(DIR);
@FILES=Compare($month,\\@FILES);# сравниваем списки файлов с логами
return @FILES if 1;
}

Здесь важна лишь строчка -> @FILES=Compare($month,\\@FILES);
то есть в функцию передаю список файлов (ссылка на массив)
Теперь код функции Compare:

sub Compare {
my $mon=shift;
my $files=shift;# ссылка на массив @FILES
return @{$files} unless(-e "./lib/data/$mon$CONFIG{\'year\'}.txt");# возвращаем полный список - если файла нет
open(LIST,"<","./lib/data/$mon$CONFIG{\'year\'}.txt")|| GetError("Can\'t open data file $mon$CONFIG{\'year\'}: $!");
my @LIST=;
close(LIST);
### вот он уже десятый вариант кода... этот кусок самый тупой... ##########
my($i,$y);
for($i=0;$i<=scalar @{$files};$i++) {
   for($y=0;$y<=scalar @LIST; $y++) {
      shift @{$files} if($files->[$i] eq $LIST[$y]);
      }
   }
#############################
return @{$files};      
}


В общем-то я пришел к самому идиотскому варианту... как видите.
Название: Сравнить два массива
Отправлено: commander от 21 Апреля 2005, 11:32:20
Цитировать
этот кусок самый тупой...

какой? вот этот:
my($i,$y);
for($i=0;$i<=scalar @{$files};$i++) {
   for($y=0;$y<=scalar @LIST; $y++) {
      shift @{$files} if($files->[$i] eq $LIST[$y]);
      }
   }
?

если так... то конечно можно переписать его так:
my @arr=("1.txt", "2.exe", "3.dll");
my @files=("1.txt", "2.exe", "5.dll");
map {
 for my $wrong_file(@files)
 {
  shift @arr if($wrong_file eq $_);
 }
}@arr;
print @arr;
но идея от этого не поненяеться... и прирост скорости будет тожк не большой... :)
Название: Сравнить два массива
Отправлено: cr4ck3r от 21 Апреля 2005, 11:43:09
Да кусок этот.. :(
Название: Сравнить два массива
Отправлено: AnnA от 21 Апреля 2005, 11:47:41
cr4ck3r
а почему вы не хотите сравнивать с помощью хэша? Насколько я знаю - верный вариант исключения повторяющихся значений.
Название: Сравнить два массива
Отправлено: commander от 21 Апреля 2005, 11:48:41
cr4ck3r
ну возращаемся к основам программирования... есть два массива... как из одного вычесть содержание другого кроме как перебором?
Название: Сравнить два массива
Отправлено: cr4ck3r от 21 Апреля 2005, 12:12:31
2AnnA: Я пробовал так. Объединял два массива в один и обрабатывал через хэш - то есть как вы говорите исключал повторяющиеся значения - но на выходе я просто получаю уникальные элементы - а мне нужно только те что не содержатся в текстовом файле.
2commander: да... щас попробую вспомнить... (заставлю мозг работать).
Название: Сравнить два массива
Отправлено: Green Kakadu от 21 Апреля 2005, 12:56:29
Цитировать
cr4ck3r:
Объединял два массива в один и обрабатывал через хэш - то есть как вы говорите исключал повторяющиеся значения

В Perl CookBook есть пример для этого
Название: Сравнить два массива
Отправлено: cr4ck3r от 21 Апреля 2005, 13:05:13
................... случайный повтор ........................
Название: Сравнить два массива
Отправлено: cr4ck3r от 21 Апреля 2005, 13:06:17
Ага. Нашел. Правда в другой книжечке, но все равно спасибо всем. Код такой:

sub Compare {
my $mon=shift;
my $files=shift;# ссылка на массив @FILES
return @{$files} unless(-e "./lib/data/$mon$CONFIG{\'year\'}.txt");# возвращаем полный список - если файла нет
open(LIST,"<","./lib/data/$mon$CONFIG{\'year\'}.txt")|| GetError("Can\'t open data file $mon$CONFIG{\'year\'}: $!");
my @LIST=;
close(LIST);
### вот он! ##########
my %seen=();
foreach (@LIST) {
      chomp;
      $seen{$_}=1;
}
my @clean=grep(! $seen{$_}, @{$files});
#############################
return @clean;      
}