Forum Webscript.Ru
Программирование => Perl => Тема начата: cr4ck3r от 21 Апреля 2005, 11:00:27
-
Что-то я туплю немного. Подскажите как наиболее эффективно решить такую задачу:
Имеется массив со списком имен файлов. Имеется текстовый файл, также со списком имен файлов. Требуется, из массива удалить имена файлов которые встречаются в текстовом файле, и получить в результате список файлов которые не упоминаются в текстовом файле. Что-то я никак не могу найти нужного решения, а точнее наиболее эффективного и быстрого.
-
cr4ck3r
за тебя весь код написать? приведи хоть код своего, как ты считаешь, не эфективного решения... посмотрим если надо оптимизуруем...
-
Сори. Забыл.
Код в общем-то еще в очеь черновом варианте, поэтому не пугайтесь некоторых конструкций - они для дебаггинга.
В общем-то тут наверно стоит привести две функции:
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};
}
В общем-то я пришел к самому идиотскому варианту... как видите.
-
этот кусок самый тупой...
какой? вот этот:
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
а почему вы не хотите сравнивать с помощью хэша? Насколько я знаю - верный вариант исключения повторяющихся значений.
-
cr4ck3r
ну возращаемся к основам программирования... есть два массива... как из одного вычесть содержание другого кроме как перебором?
-
2AnnA: Я пробовал так. Объединял два массива в один и обрабатывал через хэш - то есть как вы говорите исключал повторяющиеся значения - но на выходе я просто получаю уникальные элементы - а мне нужно только те что не содержатся в текстовом файле.
2commander: да... щас попробую вспомнить... (заставлю мозг работать).
-
cr4ck3r:
Объединял два массива в один и обрабатывал через хэш - то есть как вы говорите исключал повторяющиеся значения
В Perl CookBook есть пример для этого
-
................... случайный повтор ........................
-
Ага. Нашел. Правда в другой книжечке, но все равно спасибо всем. Код такой:
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;
}