Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> "вычитание" файлов. нетривиальная задача 
:(
    Опции темы
e7x
Дата 13.5.2007, 19:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 24.4.2007

Репутация: нет
Всего: нет



дано:
текстовый файл A, 
текстовый файл B

задача:
строки файла А, остутствующие в файле B записать в файл С. причем сделать это _оптимальным_ способом, затратив как можно меньше памяти и как можно меньше времени. имеется 2 решения, но они неудовлетворительны при больших объемах входных файлов.

решение #1 (опишу словами, быстрее будет)
в цикле читаем строки из A и во вложенном цикле сравниваем со строками из B. если совпадений нет, пишем в файл С
при количестве записей, например, в 100к на файл, количество итераций становится равным 10Г, времени тратится ОЧЧЕНЬ много 

решение #2 (кодом и словами)
1. читаем все строки из А в хеш, причем ключем хеша является прочитанная строка: $shash{$line} = 1;
2. читаем построчно файл B, и если defined($shash{$line}), то элемент удаляется (т.е. нашли дубль), иначе читаем следующую строку
3. пишем хеш в С

если плохо объяснил, вот примерный код:
Код

my %shash = ();
open A, 'a.txt';
while (<A>) {$shash{$_} = 1}
close A;
open B, 'b.txt';
while (<B>) {
   if (defined($shash{$_})) {delete $shash($_)}
}
close B;
open C, '>c.txt';
foreach (keys(%shash)) {print C $_}
close C;

решение #2 лучше первого в плане производительности, но хуже в плане расходования памяти. жрет просто неимоверно и вываливается с нехваткой памяти на сервере с 2Г оперативы, при тех же, в 100к строк, объемах

вопрос: существует ли какое-нибудь изящное и не очень ресурсоемкое решение? 

PM MAIL   Вверх
Nab
Дата 13.5.2007, 19:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



Цитата(e7x @  13.5.2007,  19:25 Найти цитируемый пост)
вопрос: существует ли какое-нибудь изящное и не очень ресурсоемкое решение? 

Конечно сущетвует smile и не одно ....
но для полного ответа мало данных :(
что это за строки, и упорядочены ли они, то есть 1 строка из A может встретиться в конце B, а 2 строка из A может встретиться в начале B? Это самый тяжелый вариант, но и он имеет не одно решение.....

То есть главный вопрос строки как то упорядочены? И упорядочены ли они одинаково?


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
nitr
Дата 13.5.2007, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 37
Всего: 84



e7x, ух... не хотел отвечать, очень, так сказать, вы "некультурны".

Цитата(e7x @  13.5.2007,  19:25 Найти цитируемый пост)
вопрос: существует ли какое-нибудь изящное и не очень ресурсоемкое решение? 

существует.

В тех же рецептах про это написано как минимум 4 решения. Здесь на форуме воспользуйтесь поиском, найдете эти и множетсва других - оптимальных - решений.


--------------------
PM   Вверх
e7x
Дата 13.5.2007, 20:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 24.4.2007

Репутация: нет
Всего: нет



обычные строки в ASCII (допустим, предложения английского языка), разделяются переводом строки =)
неупорядочены
PM MAIL   Вверх
Nab
Дата 13.5.2007, 21:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



а средняя длина строк?


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
korob2001
Дата 14.5.2007, 01:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 31
Всего: 61



Можно во втором решении воспользоваться не хешем, а DBM файлом. В итоге имеем тот же хеш, только на диске. После создания файла C, удалять временный DBM.
Скорость конечно же упадёт, но не до такой степени, как в первом варианте.

Это сообщение отредактировал(а) korob2001 - 14.5.2007, 01:13


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
e7x
Дата 14.5.2007, 06:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 24.4.2007

Репутация: нет
Всего: нет



размер строк - менее 255 символов, в среднем - 128 пусть будет smile

уважаемый nitr, не подскажите что за "те же рецепты"? а то я на форуме совсем недавно. поиск по обработке объемных файлов, к сожалению, ничего не дал. 

korob2001, спасибо огромное, пойду пробовать =)

Это сообщение отредактировал(а) e7x - 14.5.2007, 06:59
PM MAIL   Вверх
amg
Дата 14.5.2007, 07:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



Могу посоветовать хэшировать не сами строки, а их MD5-суммы (модуль Digest::MD5). MD5-сумма вычисляется очень быстро и занимает 16 байт. При количестве строк порядка 100 k вероятность совпадения MD5-сумм для разных строк ничтожно мала. Я сейчас проверил - на хэш из 2 М элементов (ключи - MD5-суммы) хватает 1 Г памяти (на хэш из 2.5 М элементов - уже нет).
PM MAIL   Вверх
e7x
Дата 14.5.2007, 08:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 24.4.2007

Репутация: нет
Всего: нет



amg, мд5 был бы классным решением, но исходные строки тоже надо где-то хранить
PM MAIL   Вверх
amg
Дата 14.5.2007, 09:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



Можно просто сделать второй проход по файлу В, это быстро будет.
Код

use Digest::MD5 qw(md5);
my %shash = ();
open A, 'a.txt';
while (<A>) {$shash{md5($_)} = 1}
close A;
open B, 'b.txt';
while (<B>) {
   my $md5 = md5($_);
   if (exists($shash{$md5})) {delete $shash($md5)}
}
seek (B, 0, 0);
open C, '>c.txt';
while (<B>) {
    print C if exists $shash{md5($_)};
}
close B;
close C;


Это сообщение отредактировал(а) amg - 14.5.2007, 09:22
PM MAIL   Вверх
e7x
Дата 14.5.2007, 10:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 24.4.2007

Репутация: нет
Всего: нет



amg, респект! =) буду надеяться, что хеши не будут совпадать для разных строк

(шепотом) только в примере надо наверное А перечитывать, ибо его строки нам нужны

Спасибо всем!
PM MAIL   Вверх
amg
Дата 14.5.2007, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



Цитата(e7x @  14.5.2007,  10:18 Найти цитируемый пост)
только в примере надо наверное А перечитывать, ибо его строки нам нужны
Да, конечно. Я не проверял код, прямо в форум писал.

Еще можно хэшировать файл В и пройтись по файлу А, занося все строки, которых нет в хэше, в файл С. Если файлов А и В только по одному, то это менее затратно.

И еще, думаю, имеет смысл при хэшировании подсчитывать кол-во строк и бросать все, если их становится слишком много (или переходить на другой алгоритм, как korob2001 советовал).
PM MAIL   Вверх
tishaishii
Дата 15.5.2007, 14:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Создатель
***


Профиль
Группа: Завсегдатай
Сообщений: 1262
Регистрация: 14.2.2006
Где: Москва

Репутация: 4
Всего: 8



А предложения в обоих файлах должны идти в строгой последовательности с различиями внутри и по краям?

Т.е. такая задача: файл A="abdefs", файл Б="abAebs", различия="ab*e*s"? Если я правильно понял, то таких различий должно быть множество.
PM MAIL ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0830 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.