![]() |
1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code].
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!
![]() ![]() |
![]() |
dened |
![]()
Сообщение
#1
|
Группа: Пользователи Сообщений: 4 Пол: Мужской Репутация: ![]() ![]() ![]() |
Суть задачи такая.
Нужно удалить из текстового файла повторяющиеся слова. Причем текстовый файл очень большой, порядка 200 000 строк и повторяющихся слов там тоже очень много ![]() Пример мама папа мама бабушка дед мама Результат должен быть мама папа бабушка дед Может это уже решалось здесь, но честное слово искал около часа. Находил тока работу с символами. Хотя может это и почти одно и тоже. |
Lapp |
![]()
Сообщение
#2
|
![]() Уникум ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модераторы Сообщений: 6 823 Пол: Мужской Реальное имя: Лопáрь (Андрей) Репутация: ![]() ![]() ![]() |
Решение включает в себя две основных задачи:
1. составление словаря; 2. поиск по словарю. Поскольку размер словаря может быть весьма немалым, и заранее он неизвестен, то желательно использовать динамическую память. При указанном количестве строк и колличество слов может значительно превышать возможности сегмента (64К), так что придется структурировать. Если использование ТР не обязательно, то рекомендую взять 32-битный сомпилятор (например, FPC). Структурирование все равно весьма желательно для ускорения работы и уменьшения размеров. Структура базы данных (словаря) может быть как самой простой (слова в одном массиве of char, разделенные пробелами в алфавитном порядке), так и более сложной Например, блоки описанной струтуры, пронумерованные буквами - или парами, тройками букв. Вот наглядная иллюстрация сказанного: 1-й способ (1): а агат аз азот астра аська береза боб бор бочка вода воск восток дед дело дочь дочка 2-й способ с нумерацией одной буквой (2): !а ? гат з зот стра ська !б ереза об ор очка !в ода оск осток !д ед ело очь очка 2-й способ с нумерацией двумя буквами (3): 1а ? 2г ат 2з ? от 2с тра ька 1б 2е реза 2о б р чка 1в 2о да ск сток 1д 2е д ло 2о чь чка "?" означает слово без продолжение, только из нумерующих букв. Реально этот знак не нужен - два пробела подряд выполняют его роль. Даже на глаз видно, что (2) выигрывает по объему по сравнению с (1). Способ (3) на первый взгляд и сложнее, и места больше требует. Про сложность спорить не буду, но выигрыш в месте там будет заметен при бОльшем размере словаря. Вот, примерно так.. Выбирай, что нарвится ![]() Да, еще про поиск.. Его можно вести дихотомией с самого начала - либо можно хранить карту пронумерованных блоков. Внутри блока - дихотомия.. ![]() Ну, а само удаление слов - дело несложное.. ломать - не делать! ![]() PS Уточни также, что считать разделителями слов. Надеюсь, только пробелы.. -------------------- я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой |
volvo |
![]()
Сообщение
#3
|
Гость ![]() |
Цитата Если использование ТР не обязательно, то рекомендую взять 32-битный сомпилятор (например, FPC) И тогда задача будет решаться в несколько строк, ибо TStringList + Duplicates |
Lapp |
![]()
Сообщение
#4
|
![]() Уникум ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модераторы Сообщений: 6 823 Пол: Мужской Реальное имя: Лопáрь (Андрей) Репутация: ![]() ![]() ![]() |
И тогда задача будет решаться в несколько строк, ибо TStringList + Duplicates ![]() Ну, скажем так: я имел в виду подмножество FPC, примерно равное TP, за исключением сквозной адресации памяти. То есть сам язык, а не библиотеки.. Мне это кажется разумным при изучении языка - мало смысла в том, чтоб извращаться с двадцатибитной адресацией типа сегмент-смещение.. Хотя, опрекделенный смысл, конечно, есть - и пусть автор темы решает этот вопрос сам (с помощью препа, полагаю.. ![]() -------------------- я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой |
klem4 |
![]()
Сообщение
#5
|
![]() Perl. Just code it! ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модераторы Сообщений: 4 100 Пол: Мужской Реальное имя: Андрей Репутация: ![]() ![]() ![]() |
В принципе, если повторяющихся строк очень много и ограничения по времени не критичны, то можно обойтись без массивов, используя временный файл.
-------------------- perl -e 'print for (map{chr(hex)}("4861707079204E6577205965617221"=~/(.{2})/g)), "\n";'
|
dened |
![]()
Сообщение
#6
|
Группа: Пользователи Сообщений: 4 Пол: Мужской Репутация: ![]() ![]() ![]() |
PS Уточни также, что считать разделителями слов. Надеюсь, только пробелы.. Разделителем является enter. Lapp ![]() Мое решение, то есть пока идея, такова Создать новый файл и копировать туда слова. берем новое слово и ищем его во втором файле, если нет, то записываем, иначе берем следующие слово из первого файла ![]() Зы: как я понял обращатся к определенному участку текстового файла нельзя?? или можно, если можно подскажите плиз функцию или процедуру, которая это делает |
klem4 |
![]()
Сообщение
#7
|
![]() Perl. Just code it! ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модераторы Сообщений: 4 100 Пол: Мужской Реальное имя: Андрей Репутация: ![]() ![]() ![]() |
Цитата как я понял обращатся к определенному участку текстового файла нельзя Нельзя ... -------------------- perl -e 'print for (map{chr(hex)}("4861707079204E6577205965617221"=~/(.{2})/g)), "\n";'
|
dened |
![]()
Сообщение
#8
|
Группа: Пользователи Сообщений: 4 Пол: Мужской Репутация: ![]() ![]() ![]() |
Цитата Еще думаю если исключить вариант с доп. файлом, выгоднее использовать структуру типа списка ![]() |
klem4 |
![]()
Сообщение
#9
|
![]() Perl. Just code it! ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модераторы Сообщений: 4 100 Пол: Мужской Реальное имя: Андрей Репутация: ![]() ![]() ![]() |
Упс а я это убрал уже ибо про массивы ни слова не было ...
Примеров куча: Поиск + Все о динамических структурах данных. -------------------- perl -e 'print for (map{chr(hex)}("4861707079204E6577205965617221"=~/(.{2})/g)), "\n";'
|
volvo |
![]()
Сообщение
#10
|
Гость ![]() |
Цитата Мое решение, то есть пока идея, такова Это реально только для очень небольших файлов... Чем больше файл, и чем больше в нем НЕповторяющихся слов, тем дольше ты будешь проходить по новому файлу в попытке найти текущее слово из исходного файла... Я сейчас запустил написанную по этому алгоритму программу с файлом на 300000 слов , из которых около 50000 - уникальны... Уже 3 минуты, а обработано только около 40000 слов...Создать новый файл и копировать туда слова. Все-таки придется скорее всего работать с динамическими структурами... Сообщение отредактировано: volvo - 1.05.2007 13:22 |
klem4 |
![]()
Сообщение
#11
|
![]() Perl. Just code it! ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модераторы Сообщений: 4 100 Пол: Мужской Реальное имя: Андрей Репутация: ![]() ![]() ![]() |
Хм, если словарь не большой (не много разных слов), то все достаточно быстро работает ...
генирируем большой файл const Сама программа uses crt; -------------------- perl -e 'print for (map{chr(hex)}("4861707079204E6577205965617221"=~/(.{2})/g)), "\n";'
|
volvo |
![]()
Сообщение
#12
|
Гость ![]() |
Ну, со словарем из 10 слов естественно - ограничений по памяти никаких нет, тут все просто... А вот если размеры словаря зашкаливают за 2-3 тысячи, тут придется уже серьезно подумать...
Сообщение отредактировано: volvo - 1.05.2007 13:29 |
klem4 |
![]()
Сообщение
#13
|
![]() Perl. Just code it! ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модераторы Сообщений: 4 100 Пол: Мужской Реальное имя: Андрей Репутация: ![]() ![]() ![]() |
да .. сгенерил файл с рандомными словами, и прога ушла в себя
![]() -------------------- perl -e 'print for (map{chr(hex)}("4861707079204E6577205965617221"=~/(.{2})/g)), "\n";'
|
volvo |
![]()
Сообщение
#14
|
Гость ![]() |
Программа, написанная с использованием списков (деревья дадут гораздо большую скорость при поиске), отработала за 118 сек. против 49 минут по предыдущему алгоритму (слов в исходном файле - 347621, в алфавите - 24000 слов)
uses list; |
dened |
![]()
Сообщение
#15
|
Группа: Пользователи Сообщений: 4 Пол: Мужской Репутация: ![]() ![]() ![]() |
Мой пример кода, как и говорил volvo работает офигеть, как долго
Поэтому буду разбиратся с динамическими структурами. Зы: по поводу словаря. как упорядочить слова в словаре? по буквам? пока тока идея попробывать с преобразованием букв в числа, и по этому методу упорядочить. ЗЗЫ: to volvo. есть одна загвоздка, слова все русские, то есть написаны на киррилице. и поэтому массив [A..Z] не очень пригодится ![]() ![]() Сообщение отредактировано: dened - 1.05.2007 19:08 |
volvo |
![]()
Сообщение
#16
|
Гость ![]() |
Цитата есть одна загвоздка, слова все русские, то есть написаны на киррилице Это решается довольно просто:{ Пишешь функцию, корректно работающую с кириллицей } P.S. Кстати, Цитата а массив [А..Я] не работает - это как понимать? Проверить не могу, но работать должно, особенно с учетом приведенной выше функции Upcase... Множество символов 'А' .. 'Я' - неразрывно, ничего лишнего в нем не содержится... Почему ты решил, что оно не работает, и как именно "не работает"?Сообщение отредактировано: volvo - 1.05.2007 22:36 |
![]() ![]() |
![]() |
Текстовая версия | 20.07.2025 10:52 |