Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Удалить повторы слов в файле

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Без описания
seowin
Отправлено: 30 Сентября, 2015 - 14:06:25
Post Id


Новичок


Покинул форум
Сообщений всего: 16
Дата рег-ции: Апр. 2015  


Помог: 0 раз(а)




Помогите, пожалуйста, написать скрипт.

Задача следующая.
Есть txt файл, в котором строки формата:

абдикация|отречение
абзац|часть|отрывок|кусок|рождать
абитуриент|ученик|институтка|академист
абонировать|нанимать|рядить
абордаж|столкновение|сцепка|свалка
абориген|житель|туземец
абортировать|рождать
абракадабра|бессмыслица|отречение|белиберда|нелепость|ахинея|нелепица|чепуха
абсолютно|полностью|вполне|бесспорно|безусловно|непременно|совершенно
абстрактный|духовный|бессмыслица|отвлеченный
абсурд|бред|бреда|вздор|абордаж

Иногда слова в пределах разных строк повторяюся.

Задача - удалить повторы слов.

Т.е. не выходе должно быть:
абдикация|отречение
абзац|часть|отрывок|кусок|рождать
абитуриент|ученик|институтка|академист
абонировать|нанимать|рядить
абордаж|столкновение|сцепка|свалка
абориген|житель|туземец
абортировать
абракадабра|бессмыслица|белиберда|нелепость|ахинея|нелепица|чепуха
абсолютно|полностью|вполне|бесспорно|безусловно|непременно|совершенно
абстрактный|духовный|отвлеченный
абсурд|бред|бреда|вздор

Ломал голову, так и не смог написать рабочий вариант скритпа.

Не доходит, как пересохранить строку в файле.

Накидал пока вот что:
PHP:
скопировать код в буфер обмена
  1. <?PHP
  2.  
  3. $file = file('1.txt');
  4.  
  5. for($a = 0; $a < count($file); $a++) {
  6.  
  7.         $file[$a] = trim($file[$a]);
  8.        
  9.         $ex = explode('|', $file[$a]);
  10.        
  11.         foreach($ex as $val) {
  12.        
  13.         for($i = 0; $i < count($ex); $i++) {
  14.        
  15.                 for($j = $a + 1; $j < count($file); $j++) {
  16.                         if(strpos($file[$j], $ex[$i])) {
  17.                         str_replace($ex[$i], "", $file[$j]) . "<br/>";
  18.                         }
  19.                 }
  20.  
  21.         }
  22.  
  23. }
  24.  
  25. ?>
 
 Top
dcc0
Отправлено: 30 Сентября, 2015 - 14:34:26
Post Id


Участник


Покинул форум
Сообщений всего: 1043
Дата рег-ции: Июль 2014  


Помог: 10 раз(а)




Примерно вижу так:
1. Читаем файл-источник.
2. Сохраняем во временный файл весь словарь, т.е. первые слова до знака |.
3. Читаем временный файл построчно, каждую строку (одно слово) ищем в файле-источнике, если найдено и если слово стоит не на первой позиции, то удаляем.
Как сохранить? Пишем строки, в которых не нашли, в новый файл, в которых нашли тоже пишем в новый файл, но без повтора.
Когда дойдем до последней строки во временном файле, удалим временный файл, удалим старый файл и переименуем новый, присвоив ему имя старого.

Т.е. как я понимаю, надо взять первое слово, пробежаться по всему файлу, удалить, потом взять второе и т.д.
Тот код, который Вы написали, похоже, не является решением.

(Отредактировано автором: 30 Сентября, 2015 - 14:43:10)



-----
Март 2021. Бросил программирование
 
 Top
neokiev
Отправлено: 30 Сентября, 2015 - 16:05:19
Post Id


Новичок


Покинул форум
Сообщений всего: 7
Дата рег-ции: Сент. 2015  


Помог: 0 раз(а)




Если слов не очень много, то простой способ:
CODE (htmlphp):
скопировать код в буфер обмена
  1.  
  2. //читаем данные из файла
  3. $contents = file_get_contents('data.txt');
  4. //делаем массив - удаляем ненужные переносы строк и прочее
  5. $arrayOfWords = explode('|',  preg_replace('/\s+/', '',($contents)));
  6. //вуаля массив без дубликатов
  7. var_dump(array_unique($arrayOfWords));
  8. //дальше если нужно
  9. $result = implode('|', array_unique($arrayOfWords));
  10.  


Также если нужно учитывать верхний и нижний регистр слов - то смотрим в сторону strtolower

(Отредактировано автором: 30 Сентября, 2015 - 16:07:45)

 
 Top
seowin
Отправлено: 30 Сентября, 2015 - 17:12:48
Post Id


Новичок


Покинул форум
Сообщений всего: 16
Дата рег-ции: Апр. 2015  


Помог: 0 раз(а)




neokiev пишет:
Если слов не очень много, то простой способ:


Нужно, чтобы строки имели точно такой же вид, как в исходном файле, так как это база синонимов. Каждая строка отвечает за свой синонимичный ряд

(Отредактировано автором: 30 Сентября, 2015 - 17:14:07)

 
 Top
neokiev
Отправлено: 30 Сентября, 2015 - 17:34:34
Post Id


Новичок


Покинул форум
Сообщений всего: 7
Дата рег-ции: Сент. 2015  


Помог: 0 раз(а)




хорошо, нужно было описать изначально в задаче, дальше: в какой строке нужно удалять дубликат? если он есть?
(Добавление)
Код работает:
тестовые данные data.txt
CODE (htmlphp):
скопировать код в буфер обмена
  1.  
  2. asdfjasdjf|fasdfasdfas|afsdfasdfs
  3. ggggggg|ffffff|adsasda|
  4. fff|1234|8888|fffff|fff
  5. kasd|ROFL|ROFL
  6. ROFL|asda|9999
  7. OOOOP|kiko|NIKO
  8. NIKO|BOOM|LIQUID
  9.  


результат
newfile.txt
CODE (htmlphp):
скопировать код в буфер обмена
  1. asdfjasdjf|fasdfasdfas|afsdfasdfs
  2. ggggggg|ffffff|adsasda
  3. fff|1234|8888|fffff
  4. kasd|ROFL
  5. asda|9999
  6. OOOOP|kiko|NIKO
  7. BOOM|LIQUID



CODE (htmlphp):
скопировать код в буфер обмена
  1.  
  2. <?php
  3. //читаем данные из файла
  4. $contents = file_get_contents('data.txt');
  5.  
  6. //разбиваем данные по переносу строк
  7. $default = explode("\n", $contents);
  8.  
  9. $newOne = array();
  10. $appearances = array();
  11.  
  12. foreach ($default as $first => $line) {
  13. //разбиваем каждый елемент на слова
  14.    $exploded = explode('|', $line);
  15. //проходим по каждому слову
  16.   foreach($exploded as $currentItem) {
  17. //проверяем что бы елемент был не пустой, и не повторялся
  18.       if ($currentItem !== '' && !in_array($currentItem, $appearances)) {
  19.           //добавляем елемент в массив $appearances который позволяет
  20.           //исключит дубликаты
  21.           $appearances[] = $currentItem;
  22.          
  23.           $newOne[$first] .= $currentItem . '|';
  24.       }
  25.   }
  26. }
  27. //проходим по массиву новому
  28. //и удаляем последний | и добавляем вместо него перенос строки
  29. //тут можно заменить на str_replace/substrreplace
  30. $resulting = array_map(function($element) {
  31.   $removeLast = substr($element, 0, -1);
  32.    return $removeLast . "\n";
  33. }, $newOne);
  34.  
  35. $writeToFile = implode("",$resulting );
  36.  
  37. $file = fopen('newfile.txt', 'w+');
  38. fwrite($file, $writeToFile);
  39. fclose($file);
  40.  
  41.  
  42.  


код можно немного доработать, также посмотреть что бы небыло проблем с кодировкой

(Отредактировано автором: 30 Сентября, 2015 - 18:15:11)

 
 Top
dcc0
Отправлено: 30 Сентября, 2015 - 21:12:03
Post Id


Участник


Покинул форум
Сообщений всего: 1043
Дата рег-ции: Июль 2014  


Помог: 10 раз(а)




neokiev, я почему-то думаю, что решение не совсем верное.
Код несколько нарушил порядок в результате.


-----
Март 2021. Бросил программирование
 
 Top
neokiev
Отправлено: 30 Сентября, 2015 - 21:46:34
Post Id


Новичок


Покинул форум
Сообщений всего: 7
Дата рег-ции: Сент. 2015  


Помог: 0 раз(а)




dcc0 пишет:
Код несколько нарушил порядок в результате.

Ниндзя Не вижу где? Пример можно?) Подмигивание

dcc0 пишет:
neokiev, я почему-то думаю, что решение не совсем верное.

Это одно из решений. Которое можно доработать, я подсказал направление.
 
 Top
dcc0
Отправлено: 30 Сентября, 2015 - 22:26:16
Post Id


Участник


Покинул форум
Сообщений всего: 1043
Дата рег-ции: Июль 2014  


Помог: 10 раз(а)




Было ROFL|asda
Стало ROFL asda

Тут нужно уточнение автора. Я так понимаю - это
своебразеый словарь синонимов. Тут может быть важным порядок следования знаков, количество строк.
(Добавление)
Проще говоря, пример автора и Ваш результат мало изоморфны.

(Отредактировано автором: 30 Сентября, 2015 - 22:28:10)



-----
Март 2021. Бросил программирование
 
 Top
neokiev
Отправлено: 30 Сентября, 2015 - 22:55:35
Post Id


Новичок


Покинул форум
Сообщений всего: 7
Дата рег-ции: Сент. 2015  


Помог: 0 раз(а)




dcc0 пишет:

Было ROFL|asda
Стало ROFL asda


не верно вот что было и стало
CODE (htmlphp):
скопировать код в буфер обмена
  1.  
  2. kasd|ROFL|ROFL
  3. ROFL|asda|9999
  4.  
  5.  
  6. kasd|ROFL
  7. asda|9999
  8.  

это разные строки.

Суть даже не в этом, задача до конца не сформулирована. Автор, если есть возможность приведите полный пример файла, и уточните в каких случаях удалять, спасибо.
 
 Top
seowin
Отправлено: 01 Октября, 2015 - 08:24:51
Post Id


Новичок


Покинул форум
Сообщений всего: 16
Дата рег-ции: Апр. 2015  


Помог: 0 раз(а)




Спасибо за помощь.

Проверил, результат получился таким:
абдикация|отречение
абзац|часть|отрывок|кусок|рождать
абитуриент|ученик|институтка|академист
абонировать|нанимать|рядить
абордаж|столкновение|сцепка|свалка
абориген|житель|туземец
абортировать
абракадабра|бессмыслица|отречение|белиберда|нелепость|ахинея|нелепица|чепуха
абсолютно|полностью|вполне|бесспорно|безусловно|непременно|совершенно
абстрактный|духовный|отвлеченный
абсурд|бред|бреда|вздор

Т.е. не удалился повтор слова "отречение".

Полный файл имеет около 15 тыс. строк.

Нужно, чтобы каждое слово в файле встречалось всего 1 раз.
Т.е. алгоритм следующий:
1. разбиваем строку на слова
2. ищем вхождение каждого слова в каждой строке последующей строке
3. если вхождение найдено, заменяем его на ""

На выходе должен быть файл, в котором:
а) строки имеют такой же вид, как в первоначальном файле
б) заменены все повторы слов на ""

Ничего страшного, если будут строки такого вида:
абордаж||сцепка|свалка

Т.е. будут рядом две вертикальные черты "||". Главное, чтобы в пределах разных строк не было повторов слов.

Зачем это все надо:
Далее этот файл поместится в БД. При выборке какого-то конкретного одного слова, база должна возвращаться одну строку.

Сейчас же из-за повторов слов в разных строках база возвращает несколько строк, в которых находит вхождение заданного слова.
 
 Top
neokiev
Отправлено: 01 Октября, 2015 - 10:08:32
Post Id


Новичок


Покинул форум
Сообщений всего: 7
Дата рег-ции: Сент. 2015  


Помог: 0 раз(а)




А что мешает доработать скрипт который я написал выше.
используй var_dump() или xdebug и смотри где и почему слово удалилось.
И еще если вы будете использовать базу то, есть еще один вариант:
1) Можно читать из файла построчно и записывать в базу, и проверять нет ли такой записи в базе, если слово существует то не записывать, главное правильно структуру базы сделать.

(Отредактировано автором: 01 Октября, 2015 - 10:11:09)

 
 Top
dcc0
Отправлено: 01 Октября, 2015 - 11:05:04
Post Id


Участник


Покинул форум
Сообщений всего: 1043
Дата рег-ции: Июль 2014  


Помог: 10 раз(а)




seowin, т.е. первые слова в строке всегда в алфавитном порядке? И если их 15 тыс, - они от "А" до "Я" ?

(Отредактировано автором: 01 Октября, 2015 - 12:19:27)



-----
Март 2021. Бросил программирование
 
 Top
Deonis
Отправлено: 01 Октября, 2015 - 12:40:40
Post Id



Посетитель


Покинул форум
Сообщений всего: 298
Дата рег-ции: Нояб. 2009  


Помог: 14 раз(а)




seowin, т.к. файл большой и его структура такая же, как у csv-файлов, то я бы сделал так:
PHP:
скопировать код в буфер обмена
  1. $output = [];
  2. $voc = [];
  3. if (($fp = fopen('input_file.csv', 'r')) !== false) {
  4.     while (($data = fgetcsv($fp, 1000, '|')) !== false) {
  5.         $tmp = array_diff($data, $voc);
  6.         $voc = array_merge($voc,$tmp);                         
  7.         $output[] = $tmp;
  8.     }
  9.     fclose($fp);
  10. }
  11. // записываем обработанные данные в новый файл
  12. $fp = fopen('output_file.csv', 'w');
  13. foreach ($output as $fields) {
  14.     fputcsv($fp, $fields, '|');
  15. }
  16. fclose($fp);
P.S. Расширение файла не обязательно должно быть csv

(Отредактировано автором: 01 Октября, 2015 - 12:42:55)

 
 Top
andrewkard
Отправлено: 01 Октября, 2015 - 13:55:31
Post Id


Участник


Покинул форум
Сообщений всего: 1372
Дата рег-ции: Нояб. 2014  


Помог: 30 раз(а)




Еще вариант Улыбка :
PHP:
скопировать код в буфер обмена
  1.  
  2. $f = fopen('1.txt','r');
  3. $arr_test = array();
  4. $str = '';
  5. while (!feof($f)) {
  6.     $line = fgets($f);
  7.     $arr_words = explode('|',$line);
  8.     foreach ($arr_words as $index => $word){
  9.         if (in_array(trim($word), $arr_test)){
  10.            $arr_words[$index] = '';
  11.         } else {
  12.             $arr_test[] = trim($word);
  13.         }
  14.     }
  15.     $str .= join('|', $arr_words);
  16. }
  17. fclose($f);
  18.  
  19. $f = fopen('2.txt','w');
  20. fwrite($f, $str);
  21. fclose($f);
  22.  
 
 Top
seowin
Отправлено: 01 Октября, 2015 - 14:06:33
Post Id


Новичок


Покинул форум
Сообщений всего: 16
Дата рег-ции: Апр. 2015  


Помог: 0 раз(а)




Интересный способ. Большое спасибо!

Работает, как надо!

Deonis пишет:
seowin, т.к. файл большой и его структура такая же, как у csv-файлов, то я бы сделал так:
PHP:
скопировать код в буфер обмена
  1. $output = [];
  2. $voc = [];
  3. if (($fp = fopen('input_file.csv', 'r')) !== false) {
  4.     while (($data = fgetcsv($fp, 1000, '|')) !== false) {
  5.         $tmp = array_diff($data, $voc);
  6.         $voc = array_merge($voc,$tmp);                         
  7.         $output[] = $tmp;
  8.     }
  9.     fclose($fp);
  10. }
  11. // записываем обработанные данные в новый файл
  12. $fp = fopen('output_file.csv', 'w');
  13. foreach ($output as $fields) {
  14.     fputcsv($fp, $fields, '|');
  15. }
  16. fclose($fp);
P.S. Расширение файла не обязательно должно быть csv
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Вопросы новичков »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB