Нужно сравнить 2 текста и выделить различия...
Попробую лучше показать на примере.
- На входе:
- Сложные медицинские задачи имеют простые и понятные инженерам неправильные решения.
М.Козак - Сложные медицинские вопросы имеют простые и понятные для инженеров неправильные решения.
М.Коzак
- Сложные медицинские задачи имеют простые и понятные инженерам неправильные решения.
- На выходе:
- Сложные медицинские
задачиимеют простые и понятныеинженерамнеправильные решения.
М.Козак - Сложные медицинские вопросы имеют простые и понятные для инженеров неправильные решения.
© М.Коzак
- Сложные медицинские
Спустя 2 минуты, 50 секунд (1.09.2009 - 17:28) FatCat написал(а):
Нет, сравнение до первого различия легко: substr($pos,1) выкусывает символ и можно сравнивать посимвольно.
Не понимаю, как определить момент, когда различие кончилось и пошел дальше одинаковый кусок.
Не понимаю, как определить момент, когда различие кончилось и пошел дальше одинаковый кусок.
Спустя 2 минуты, 42 секунды (1.09.2009 - 17:30) solib написал(а):
ну первое что пришло в голову разбить текст на масив
$text1=explode (" ",$text);
и потом в цикле проверить различия
for($i=0; $i<=count($text1); $i++){}
хотя не думаю что это првильно. ) предложил как вариант
$text1=explode (" ",$text);
и потом в цикле проверить различия
for($i=0; $i<=count($text1); $i++){}
хотя не думаю что это првильно. ) предложил как вариант
Спустя 7 минут, 57 секунд (1.09.2009 - 17:38) solib написал(а):
хм по той схеме которую я предложил наверно не получится(((
в задачи-вопросы различие покажет
а в инженерам - для инженеров будет сбито число масивов и дальше текст будет весь как будто изменён
в задачи-вопросы различие покажет
а в инженерам - для инженеров будет сбито число масивов и дальше текст будет весь как будто изменён
Спустя 20 минут, 59 секунд (1.09.2009 - 17:59) xPoint написал(а):
можно еще вот так попробовать:
PHP |
$str1='Сложные медицинские задачи имеют простые и понятные инженерам неправильные решения. |
выводит
Цитата |
array 2 => string 'задачи' (length=12) 7 => string 'инженерам' (length=18) 9 => string 'решения. М.Козак' (length=29) |
почти то что нужно
Спустя 54 минуты, 7 секунд (1.09.2009 - 18:53) FatCat написал(а):
Посмотреть бы, как в ворде реализована функция сравнения версий... Он это классно делает.
Спустя 1 час, 41 минута, 33 секунды (1.09.2009 - 20:35) live Uucyc написал(а):
может делать цикл в цикле...первым циклом определяем символ, с которого начинается различие и запускаем второй цикл, которым определяем где закончились различия. После приравниваем счетчик первого цикла к счетчику второго и начинаем опять искать следующее различие.
У меня такая идея
У меня такая идея
Спустя 51 минута, 34 секунды (1.09.2009 - 21:27) sergeiss написал(а):
FatCat... Я попробую вспомнить, как я делал аналогичное сравнение. Только у меня были не слова, а массивы чисел. Но по своей сути задача идентичная.
Было это где-то года 2 тому тому назад.
Было это где-то года 2 тому тому назад.
Спустя 16 минут, 56 секунд (1.09.2009 - 21:43) sergeiss написал(а):
Вот, нашел код.
Идея тут такая. Есть 2 набора данных, параметры секторов сотовой связи. Первый из указанных подразумевается более ранним по дате.
Поэтому если в нем данные есть, и их нету во втором, то считается, что данные были удалены. Если данные есть во втором списке, и их нету в первом, то они были добавлены.
Если же найдены совпадающие (по ключу) записи, то тогда сравниваем их поэлементно.
Все данные записываются в массивы строк типа TStringList.
В итоге данные выводятся пользователю.
Я так думаю, что разобраться в алгоритме работы этой функции сможет любой человек, не знающий С++, но знающий ПХП
Все данные, нужные для функции, являются внешними. Т.е. они подразумеваются введенными в форму. А функция их просто берет оттуда.
Идея тут такая. Есть 2 набора данных, параметры секторов сотовой связи. Первый из указанных подразумевается более ранним по дате.
Поэтому если в нем данные есть, и их нету во втором, то считается, что данные были удалены. Если данные есть во втором списке, и их нету в первом, то они были добавлены.
Если же найдены совпадающие (по ключу) записи, то тогда сравниваем их поэлементно.
Все данные записываются в массивы строк типа TStringList.
В итоге данные выводятся пользователю.
Я так думаю, что разобраться в алгоритме работы этой функции сможет любой человек, не знающий С++, но знающий ПХП
Все данные, нужные для функции, являются внешними. Т.е. они подразумеваются введенными в форму. А функция их просто берет оттуда.
Код |
void __fastcall TFormCompare::DoCompareCell(void) { AnsiString Str, Val1, Val2, Filter=""; int Cell1, Cell2, LAC1, LAC2; bool FirstDifference; TStringList *CellsDeleted=new TStringList, *CellsNew=new TStringList, *ChangedParameters=new TStringList, *F=new TStringList; // создать фильтр if( UseFilter->Checked ) Filter=WhereFilter(); // этап 1. Построение списка сот по обеим базам Query1->SQL->Text="SELECT * from \'"+Set1->Text+"\\Cell.dbf\'"; if( Filter.Trim().Length() > 0 ) Query1->SQL->Text = Query1->SQL->Text + " where "+Filter; Query1->SQL->Text = Query1->SQL->Text +" order by LAC, CellID"; try { Query1->Open(); } catch(...) { Memo->Lines->Add( "Ошибка при формировании списка сот из 1-го набора."); Memo->Lines->Add( "Запрос: \'"+Query1->SQL->Text+"\'"); if( Query1->Active ) Query1->Close(); delete CellsDeleted; delete CellsNew; delete ChangedParameters; delete F; return; } Query2->SQL->Text="SELECT * from \'"+Set2->Text+"\\Cell.dbf\'"; if( Filter.Trim().Length() > 0 ) Query2->SQL->Text = Query2->SQL->Text + " where "+Filter; Query2->SQL->Text = Query2->SQL->Text +" order by LAC, CellID"; try { Query2->Open(); } catch(...) { Memo->Lines->Add( "Ошибка при формировании списка сот из 2-го набора."); Memo->Lines->Add( "Запрос: \'"+Query2->SQL->Text+"\'"); if( Query1->Active ) Query1->Close(); if( Query2->Active ) Query2->Close(); delete CellsDeleted; delete CellsNew; delete ChangedParameters; delete F; return; } // этап 2 - собственно проверка данных ProgressBar->Min=0; ProgressBar->Max=Query1->RecordCount; ProgressBar->Position=0; // подготовить список полей в таблице for( int i=0; i<Query1->FieldCount; i++) F->Add( Query1->FieldDefs->Items[i]->Name ); for( Query1->First(), Query2->First(); !Query1->Eof && !Query2->Eof; /* переход на следующие записи - внутри цикла */ ) { ProgressBar->Position=Query1->RecNo; Application->ProcessMessages(); Cell1=Query1->FieldByName("CellID")->AsInteger; Cell2=Query2->FieldByName("CellID")->AsInteger; LAC1=Query1->FieldByName("LAC")->AsInteger; LAC2=Query2->FieldByName("LAC")->AsInteger; if( Cell1 != Cell2 ) // не совпадают записи // без учета возможности разных LAC { if( Cell2 < Cell1 ) // во 2-м списке новая запись { Str=Str.sprintf("Новая сота LAC-CellID = %d-%d (CellRef=%d)", LAC2, Cell2, Query2->FieldByName("CellRef")->AsInteger); CellsNew->Add( Str ); Query2->Next(); } else { Str=Str.sprintf("Удалена сота LAC-CellID = %d-%d (CellRef=%d)", LAC1, Cell1, Query1->FieldByName("CellRef")->AsInteger); CellsDeleted->Add( Str ); Query1->Next(); } continue; } else // если записи совпадают, // то надо сравнить их поэлементно // функция DoCompareParameters как раз это и делает { DoCompareParameters( ChangedParameters, F, 1, LAC1, Cell1, LAC1, Cell1 ); Query1->Next(); Query2->Next(); } } // конец цикла по первому набору данных Memo->Lines->Add( "Различия между конфигурациями"); Memo->Lines->Add( "\'" + Set1->Text.Trim() + "\' и " ); Memo->Lines->Add( "\'" + Set2->Text.Trim() + "\'" ); if( Filter.Trim().Length() > 0 ) Memo->Lines->Add( "При использовании фильтра \'"+Filter+"\'" ); Memo->Lines->Add( "" ); if( CellsNew->Count > 0 || CellsDeleted->Count > 0 || ChangedParameters->Count > 0 ) Memo->Lines->Add( "Данные по секторам." ); else Memo->Lines->Add( "По секторам изменений нет." ); if( CellsNew->Count > 0 ) { Memo->Lines->Add( "" ); Memo->Lines->AddStrings( CellsNew ); } if( CellsDeleted->Count > 0 ) { Memo->Lines->Add( "" ); Memo->Lines->AddStrings( CellsDeleted ); } if( ChangedParameters->Count > 0 ) { Memo->Lines->Add( "" ); Memo->Lines->Add( "Измененные параметры секторов:" ); Memo->Lines->AddStrings( ChangedParameters ); } Query1->Close(); // Active=false; Query2->Close(); // Active=false; delete CellsDeleted; delete CellsNew; delete ChangedParameters; delete F; } |
Спустя 1 час, 5 минут, 28 секунд (1.09.2009 - 22:49) Krevedko написал(а):
нет слов просто. оказалось, что я не знаю пхп )
Спустя 9 минут, 17 секунд (1.09.2009 - 22:58) xPoint написал(а):
эт не пхп, это С++ (кажется борландовски, поправьте если ошибаюсь)
Спустя 21 минута, 47 секунд (1.09.2009 - 23:20) sergeiss написал(а):
xPoint - да, ты прав.
Но Krevedko подразумевал, как я понял, мою фразу "Я так думаю, что разобраться в алгоритме работы этой функции сможет любой человек, не знающий С++, но знающий ПХП". Вот он и говорит, мол, "нихт ферштейен".
Но если он же посмотрит внимательно, то увидит структуру языка, подобную ПХП. Циклы, сравнения, формат записи...
Но Krevedko подразумевал, как я понял, мою фразу "Я так думаю, что разобраться в алгоритме работы этой функции сможет любой человек, не знающий С++, но знающий ПХП". Вот он и говорит, мол, "нихт ферштейен".
Но если он же посмотрит внимательно, то увидит структуру языка, подобную ПХП. Циклы, сравнения, формат записи...
Спустя 17 минут, 23 секунды (1.09.2009 - 23:37) SunSet написал(а):
Krevedko
Лишний раз убеждаюсь, что в такие топы лучше не заглядывать, дабы себя не огорчать
FatCat
Кстати, а почему в новичках такая тема?)) Что уж постить в "Для профи"..
Лишний раз убеждаюсь, что в такие топы лучше не заглядывать, дабы себя не огорчать
FatCat
Кстати, а почему в новичках такая тема?)) Что уж постить в "Для профи"..
Спустя 1 час, 16 минут, 6 секунд (2.09.2009 - 00:54) FatCat написал(а):
Цитата (sergeiss @ 1.09.2009 - 22:43) |
Все данные записываются в массивы строк |
Дык в том для меня и вопрос, как разбить текст на массив элементов для сравнения...
Менять ся же может одна буква, а может десяток абзацев: заменяться, удаляться, добавляться...
Спустя 7 часов, 44 секунды (2.09.2009 - 07:54) sergeiss написал(а):
FatCat - так а в чем проблема-то? Используем explode, получаем 2 массива. А потом идем по ним "параллельно", как у меня в приведенной мной функции. И сравниваем поэлементно. Нашли различие - поставили какую-то метку (в отдельном массиве для каждого текста).
Собственно говоря, сравнение в моей функции занимает строчек 10-15 где-то.
Собственно говоря, сравнение в моей функции занимает строчек 10-15 где-то.
Спустя 2 часа, 33 секунды (2.09.2009 - 09:55) FatCat написал(а):
Цитата (sergeiss @ 2.09.2009 - 08:54) |
Используем explode, получаем 2 массива. |
По какому символу эксплодить? По пробелу?
А если изменена одна буква?
Сравнивать 2 массива букв? Что-то я сомневаюсь, что мы получим результат сравнения...
Я вроде сообразил как сделать. И нифига не массивами вообще. Потому что искать следует не различия, а сходства. Текст изначально считается разным, и затем ищутся совпадающие блоки текста и с них снимается раскраска. Попробую реализовать в виде кодов, посмотрим, что покажет в полевых испытаниях.
Спустя 1 час, 4 минуты, 51 секунда (2.09.2009 - 11:00) glock18 написал(а):
Цитата |
Я вроде сообразил как сделать. И нифига не массивами вообще. Потому что искать следует не различия, а сходства. Текст изначально считается разным, и затем ищутся совпадающие блоки текста и с них снимается раскраска. Попробую реализовать в виде кодов, посмотрим, что покажет в полевых испытаниях. |
Я к тому же дошел. Вообще то изначально попробовал это реализовать на добровольных началах, но дело пошло не очень то удачно. Единственное, что я понял точно нужно искать совпадающие куски (при этом кусок должен быть больше 1 символа обязательно) - я ставил три символа. По идее при таком подходе, приведенные две строки будут распарсены именно так, как раскрашены они в этом топике. Дальше идеи я правда недалеко ушел.
Спустя 56 минут, 10 секунд (2.09.2009 - 11:56) sergeiss написал(а):
FatCat - ты вредитель и провокатор А также меньшевик, гегельянец и оппортунист...
Я "убил" где-то часа 2-3 рабочего времени, деля его между этой задачей и основными задачами по своей работе!
Но!!! В итоге все-таки сделал так, что находятся полные слова, различающиеся между 2-мя строками.
В примере $str1 - строка из хэлпа (преобразуется в массив $arr1), $str2 ($arr2) - эта же строка, только модифицированная. На выходе - 2 массива, $added и $deleted, содержащие соответственно добавленные и удаленные слова. Ключи в массиве $added соответствуют ключам из $arr2, а ключи в $deleted - ключам в $arr1.
Всё остальное прокомментировано внутри.
Ну, а уж искать расхождения по букоФФкам... Я думаю можно, но это уж без меня как-нибудь
Вобщем-то, можно, я думаю, уже по окончании поиска расхождений слов поковыраться с найденными словами, с учетом их позиций... Но, как я сказал, это уж без меня как-нибудь.
Я "убил" где-то часа 2-3 рабочего времени, деля его между этой задачей и основными задачами по своей работе!
Но!!! В итоге все-таки сделал так, что находятся полные слова, различающиеся между 2-мя строками.
В примере $str1 - строка из хэлпа (преобразуется в массив $arr1), $str2 ($arr2) - эта же строка, только модифицированная. На выходе - 2 массива, $added и $deleted, содержащие соответственно добавленные и удаленные слова. Ключи в массиве $added соответствуют ключам из $arr2, а ключи в $deleted - ключам в $arr1.
Всё остальное прокомментировано внутри.
Ну, а уж искать расхождения по букоФФкам... Я думаю можно, но это уж без меня как-нибудь
Вобщем-то, можно, я думаю, уже по окончании поиска расхождений слов поковыраться с найденными словами, с учетом их позиций... Но, как я сказал, это уж без меня как-нибудь.
PHP |
// функция возвращает количество элементов массива $a, после которых находим слово (элемент массива), совпадающее со строкой $s |
На выходе получаем ожидаемый результат:
Код |
Added :Array ( [2] => что [6] => только [7] => одно [8] => измерение ) Deleted : Array ( [5] => более [6] => одного [7] => измерения [12] => ни [13] => хрена [14] => не ) |
Спустя 6 часов, 41 минута, 21 секунда (2.09.2009 - 18:37) FatCat написал(а):
Цитата (sergeiss @ 2.09.2009 - 12:56) |
В итоге все-таки сделал так, что находятся полные слова, различающиеся между 2-мя строками. |
У меня вроде получается сделать сравнение с точностью до оного символа. Сейчас маюсь с html-тегами, чтобы теги разметки не попадали внутрь тега если у фразы например жирность на курсив поменяли.
И ни фига не массивами.
Идея довольно проста.
1. Ползем от начала текста, ищем первое различие. Отрезаем.
2. Ползем справа налево от конца текста до первого различия. Отрезаем.
3. В имеющемся тексте ищем сходства: ползем посимвольно и проверяем на уникальные совпадения; в начало таких кусков ставим закрывающий тег, в конец таких кусков открывающий.
Да, конечно, не без хитросетй, иначе вложенный цикл по числу символов сожрет слишком много ресурсов. Хитрость в том, что по инкременту нарастает отступ и длина сверяемого куска; как получили уникальность совпадения - так стали расползаться в обе стороны, выбирая таким образом весь кусок уникального совпадения.
Спустя 2 часа, 22 минуты, 13 секунд (2.09.2009 - 20:59) FatCat написал(а):
Yes!!!! Я сделал это!
Спустя 1 день, 50 минут, 33 секунды (3.09.2009 - 21:50) FatCat написал(а):
Спустя 4 минуты, 31 секунда (3.09.2009 - 21:54) SunSet написал(а):
FatCat
Вещь, вроде, полезная, только мало где применима..
Подскажи, а для чего к скриптам приделывают время его генерирования? Для наочности просто?
Вещь, вроде, полезная, только мало где применима..
Подскажи, а для чего к скриптам приделывают время его генерирования? Для наочности просто?
Спустя 4 минуты, 34 секунды (3.09.2009 - 21:59) FatCat написал(а):
Цитата (SunSet @ 3.09.2009 - 22:54) |
для чего к скриптам приделывают время его генерирования? |
Скрипт кушает немало ресурсов. Таймер помогает оценить в цифрах это "немало".
Спустя 2 минуты, 48 секунд (3.09.2009 - 22:02) SunSet написал(а):
FatCat
А этот таймер прикручивается именно к конкретному скрипту или ко всей загружаемой странице? Штука полезная как вижу..
А этот таймер прикручивается именно к конкретному скрипту или ко всей загружаемой странице? Штука полезная как вижу..
Спустя 2 минуты, 17 секунд (3.09.2009 - 22:04) FatCat написал(а):
К скрипту. Время загрузки страницы пользователем меня не интересует.
Спустя 1 месяц, 20 дней, 22 часа, 1 минута, 42 секунды (24.10.2009 - 20:06) alko написал(а):
Вот правильная реализация www.easywebscripts.net/php/php_text_differences.php
_____________
Бесплатному сыру в дырки не заглядывают...