Scripts discussion (3)

Discuss and announce AkelPad plugins
Locked
  • Author
  • Message
Offline
Posts: 1162
Joined: Sun Oct 20, 2013 11:44 am

Post by Skif_off »

SFC wrote:> P.S. По хорошему ещё, наверное, выпиливать аббревиатуры и сокращения (dr. и прочее).

Не думаю. Пусть будет общее правило: удалять знаки препинания и сравнивать. Абревиатуры будут в словаре - и оно будет работать так как сейчас есть.
"Dr. Watson" превратиться в "Dr" и "Watson", как-то это не так, хотя да, по идее можно убрать, добавив "dr" в словарь.
SFC wrote:По идее или fr554 должно остаться или fr. Тут я сам не соображу.
Если текст будет не художественный, то, например, "RFS207-9, RFS2079" превратиться в "rfs", что вряд ли будет понятно сразу, тогда лучше не убирать цифры.
SFC wrote:Замечание:
От hgfh остается hgf
т.е. съедается последний символ. И так у любого последнего слова.
Прошу прощения, не заметил, это из-за

Code: Select all

AkelPad.ReplaceSel(pText.substr(0, pText.length - 1));
Убрал метод substr().
SFC wrote:Я добавил третью строку:
nod's far
nod's - исчезает, а должен остаться. И от hgfh остается hgf все равно
Вроде исправил, это от первых вариантов осталось, "don't" превращалось в "don" и "t", что неправильно.
SFC wrote:Вот так вроде нормально делает первый шаг - приводит в столбец:
См. строку 46

Есть проблема: как оставить слова с цифрами, подождём, может быть, у кого-нибудь ещё будут идеи.

Offline
Posts: 202
Joined: Sat Mar 28, 2015 2:36 pm
Location: Russia

Post by Kley »

SFC wrote:Когда читаешь англ текст встречаются незнакомые слова. Хотелось бы не читая текста сразу определить какие слова незнакомые чтобы заранее их выучить и уже спокойно читать текст.
Ключевое "слова". Зачем выучивать fr554? Это не слово, не англ. слово, не русское...
Может стоит создать еще один файл (файл исключений), куда юзер будет вносить слова, типа "the, fr, do, not" - "знакомые" со школьной скамьи. Эти слова удалять до всей обработки.
p.s.

Code: Select all

AkelPad.ReplaceSel(pText.substr(0, pText.length - 1));
строка удаляла союзы и все одиночные символы

SFC
Offline
Posts: 24
Joined: Sun Jul 12, 2015 9:37 am

Post by SFC »

Skif_off
Все работает. Давайте пока на этом остановимся.
Подумаем. По горячим следам - все работает идеально вроде. Позже накоплю статистику - выскажу критику если она будет конечно.

Слова с цифрами убирает - так и должно быть. Kley прав.
Слова из одной буквы убирает - это также есть ОК.

Создавать еще один файл = исключений нет смысла. Это и есть единственный файл dictionary со всеми словами которые надо убирать и т.д.

Большое спасибо :)

Добавлено:

Великолепно. Сейчас поместил в словарь Longman 9000. и проверил новость от BBC. Результат ожидаем.

Спс!!!

Offline
Posts: 1162
Joined: Sun Oct 20, 2013 11:44 am

Post by Skif_off »

Kley wrote:

Code: Select all

AkelPad.ReplaceSel(pText.substr(0, pText.length - 1));
строка удаляла союзы и все одиночные символы
Одиночные символы, так понимаю, убираются здесь

Code: Select all

  if (aWordList[i].length > 1)
    pText += aWordList[i] + "\r";
substr() возвращает не всю строку.

Offline
Posts: 202
Joined: Sat Mar 28, 2015 2:36 pm
Location: Russia

Post by Kley »

Skif_off
"Заказчик" доволен, ну и слава Богу.
SFC wrote:чтобы сделать неск копий скрипта на случаи разных языков
Хотя вряд ли он пробовал с "разными языками". Ведь скрипт напрочь удаляет все "нелатинские" символы.

Добавлено.
Skif_off,
извините меня приставучего и торопыгу. Возможно я просто не разобрался, но нужна ли функция Dubl?
GetWords уже просто не добавляет дубли. И pText.sort() тоже она делает.

Offline
Posts: 1162
Joined: Sun Oct 20, 2013 11:44 am

Post by Skif_off »

Kley
Согласен, в таком виде ни к чему, исправил.
SFC wrote:сделать неск копий скрипта на случаи разных языков.
Как вариант - составить список символов, типа французский (исходя из предположения, что toLowerCase() корректно сработает со всеми буквами):

Code: Select all

[a-z\u0153\u00E0\u00E2\u00E6\u00E7\u00E8\u00E9\u00EA\u00EB\u00EE\u00EF\u00F1\u00F4\u00F9\u00FB\u00FC\u00FF]
Но не знаю, какие языки, брать все по алфавиту - не вариант :)

KDJ
Offline
Posts: 1949
Joined: Sat Mar 06, 2010 7:40 pm
Location: Poland

Post by KDJ »

SFC, Skif_off, Kley
A little simpler code, without sorting (it should work faster):

Code: Select all

var aWord;
var oDict;
var oDupl;
var i;

if (aWord = AkelPad.GetTextRange(0, -1).toLowerCase().match(/[^\s`"\\\|\[\]\(\)\{\}<>,\.;:\+\-=~!#\$%\^&\*\/\?«»\d]+/g))
{
  oDict = GetDictionary();
  oDupl = {};

  for (i = aWord.length - 1; i >= 0; --i)
  {
    if ((aWord[i] in oDict) || (aWord[i] in oDupl))
      aWord.splice(i, 1);
    else
      oDupl[aWord[i]] = true;
  }

  AkelPad.SetSel(0, -1);
  AkelPad.ReplaceSel(aWord.join("\r\n"), -1);
}

function GetDictionary()
{
  var aDict = AkelPad.ReadFile(AkelPad.GetAkelDir(1) + "\\Tools\\dictionary.txt", 0x10 /*OD_ADT_NOMESSAGES*/, 65001 /*UTF-8*/, 0).split(/[\r\n]+/);
  var oDict = {};
  var i;

  for (i = 0; i < aDict.length; ++i)
    oDict[aDict[i]] = true;

  return oDict;
}

Offline
Posts: 1162
Joined: Sun Oct 20, 2013 11:44 am

Post by Skif_off »

KDJ wrote:without sorting (it should work faster)
But with sorting is more comfortable :)
Words with numbers are not needed and required certain language only (not all words).
My JScript knowledges is bad and now I don't know how better to do :)

Is replace() more fast than splice()? And if the array is very large?

Offline
Posts: 202
Joined: Sat Mar 28, 2015 2:36 pm
Location: Russia

Post by Kley »

Skif_off
Первое сообщение SFC, по этой теме, скопировал несколько сот раз в файл. Получилось ~110 000 строк (файл ~13M).
Ваш скрипт работал буквально пару секунд. Куда уж быстрей :D

Offline
Posts: 1162
Joined: Sun Oct 20, 2013 11:44 am

Post by Skif_off »

Kley
Вопрос про скорость в значительной мере теоретический, а не про конкретный скрипт: гуглил, но так и не понял, что происходит с массивом при использовании splice(). По идее удаление ячейки в произвольном месте сдвинет ячейки ниже и заставит пересчитать индексы? Тогда с большим массивом понадобится больше ресурсов и выше шанс ошибки, чем при работе со строкой. Гипотетически.

KDJ
Offline
Posts: 1949
Joined: Sat Mar 06, 2010 7:40 pm
Location: Poland

Post by KDJ »

Skif_off
About splice method you can read here: http://www.w3schools.com/jsref/jsref_splice.asp
It seems to me that the operations on long strings (eg. concatenation, replace) are slower than operations on the arrays.
For speed test you can use as text AkelHistory-Eng.txt, English dictionary from PSPad: http://www.pspad.com/en/download.php#dictionary and scripts:

Code: Select all

// Отсюда http://akelpad.sourceforge.net/forum/viewtopic.php?p=29871#p29871 и ниже,
// скрипт http://akelpad.sourceforge.net/forum/viewtopic.php?p=29873#p29873
// 2015-11-16

var nTime = new Date().getTime();
var pText = AkelPad.GetTextRange(0, -1).toLowerCase();
var aWordList = GetWords(pText);
var aDict;

pText = "";

for (i = 0; i < aWordList.length; ++i)
{
  if (aWordList[i].length > 1)
    pText += aWordList[i] + "\r";
}
// Читаем \AkelFiles\Tools\dictionary.txt (в UTF-8 без BOM) и режем в массив
aDict = AkelPad.ReadFile(AkelPad.GetAkelDir(1) + "\\Tools\\dictionary.txt", 0x10 /*OD_ADT_NOMESSAGES*/, 65001 /*UTF-8*/, false).split(/[\r\n]+/);
// Ищем в тексте документа слова из массива, если есть - удаляем
for (var i = 0; i < aDict.length; i++)
{
  if (pText.indexOf(aDict[i]) >= 0)
  {
    oPattern = new RegExp("^" + aDict[i] + "\r+", "gm");
    pText = pText.replace(oPattern, "");
  }
}
// Вставляем отсутствующие слова в документ, заменяя существующий текст
AkelPad.SetSel(0, -1);
AkelPad.ReplaceSel(pText);

WScript.Echo("Time: " + (new Date().getTime() - nTime) + " ms");

// Kley, http://akelpad.sourceforge.net/forum/viewtopic.php?p=29879#p29879
function GetWords(pText)
{
  var aAllWords;
  var nAllWords;
  var aWords = [];
  var sWord;
  var i = 0;

  aAllWords = pText.match(/[^\s`"\\\|\[\]\(\)\{\}<>,\.;:\+\-=~!#\$%^&\*/\?«»]+/g);
  nAllWords = aAllWords ? aAllWords.length : 0;

  if (nAllWords)
  {
    aAllWords.sort();

    while (i < nAllWords)
    {
      sWord = aAllWords[i];
      ++i;
      while ((i < nAllWords) && (sWord == aAllWords[i]))
      {
        ++i;
      }
      // Пропускаем итерацию, если в строке содержится что-нибудь кроме "a-z'"
      if (sWord.search(/[^a-z']+/g) >= 0) continue;
      aWords.push(sWord);
    }
  }
  return aWords;
}

Code: Select all

var nTime = new Date().getTime();
var aWord;
var oDict;
var i;

//if (aWord = AkelPad.GetTextRange(0, -1).toLowerCase().match(/[^\s`"\\\|\[\]\(\)\{\}<>,\.;:\+\-=~!#\$%\^&\*\/\?«»\d]+/g))
if (aWord = AkelPad.GetTextRange(0, -1).toLowerCase().match(/[^\s`"\\\|\[\]\(\)\{\}<>,\.;:\+\-=~!#\$%\^&\*\/\?«»]+/g))
{
  oDict = GetDictionary();

  for (i = aWord.length - 1; i >= 0; --i)
  {
//    if (aWord[i] in oDict)
    if ((aWord[i] in oDict) || (aWord[i].length == 1) || (/[^a-z']+/.test(aWord[i])))
      aWord.splice(i, 1);
    else
      oDict[aWord[i]] = true;
  }

  AkelPad.SetSel(0, -1);
  AkelPad.ReplaceSel(aWord.join("\r"), -1);
}

WScript.Echo("Time: " + (new Date().getTime() - nTime) + " ms");

function GetDictionary()
{
  var aDict = AkelPad.ReadFile(AkelPad.GetAkelDir(1) + "\\Tools\\dictionary.txt", 0x10 /*OD_ADT_NOMESSAGES*/, 65001 /*UTF-8*/, 0).split(/[\r\n]+/);
  var oDict = {};
  var i;

  for (i = 0; i < aDict.length; ++i)
    oDict[aDict[i]] = true;

  return oDict;
}

SFC
Offline
Posts: 24
Joined: Sun Jul 12, 2015 9:37 am

Post by SFC »

KDJ
Thanks for your work.
But as for me I'd like to get instrument. I got its already.

I tested its both scripts.
dictionary = 7838 words = 71,930 b

1.
file1 = 594,032 b = repeated first test many times.
Skif_off's DIC1 = 384 - 395 ms SORTED
KDJ's DIC2 = 419 - 429 ms and result is NOT SORTED

2.
file2 = 56,663,217 b = LDOCE6 xml code
DIC1 = 37877 - 38295 ms
DIC2 = AkelPAD gets into frozen status. maybe it gets loop encircle
maybe for other data...

I set both scripts for use for sorted or non-sorted results AND COMPARE RESULT for mistakes
Thanks

KDJ
Offline
Posts: 1949
Joined: Sat Mar 06, 2010 7:40 pm
Location: Poland

Post by KDJ »

SFC
This version should work faster (with sorting and without sorting):

Code: Select all

var nChoice;
var nTime;
var aWordAll;
var aWord;
var oDict;
var i;

nChoice = AkelPad.MessageBox(AkelPad.GetMainWnd(), "Do you want to sort the output words?", WScript.ScriptName, 0x23 /*MB_ICONQUESTION|MB_YESNOCANCEL*/);

if (nChoice == 2 /*IDCANCEL*/)
  WScript.Quit();

nTime = new Date().getTime();

if (aWordAll = AkelPad.GetTextRange(0, -1).toLowerCase().match(/[a-z']{2,}/g))
{
  aWord = [];
  oDict = GetDictionary();

  for (i = 0; i < aWordAll.length; ++i)
  {
    if (! (aWordAll[i] in oDict))
    {
      aWord.push(aWordAll[i]);
      oDict[aWordAll[i]] = true;
    }
  }

  if (nChoice == 6 /*IDYES*/)
    aWord.sort();

  AkelPad.SetSel(0, -1);
  AkelPad.ReplaceSel(aWord.join("\r"), -1);
}

WScript.Echo("Time: " + (new Date().getTime() - nTime) + " ms");

function GetDictionary()
{
  var aDict = AkelPad.ReadFile(AkelPad.GetAkelDir(1) + "\\Tools\\dictionary.txt", 0x10 /*OD_ADT_NOMESSAGES*/, 65001 /*UTF-8*/, 0).toLowerCase().split(/[\r\n]+/);
  var oDict = {};
  var i;

  for (i = 0; i < aDict.length; ++i)
    oDict[aDict[i]] = true;

  return oDict;
}

SFC
Offline
Posts: 24
Joined: Sun Jul 12, 2015 9:37 am

Post by SFC »

KDJ wrote:This version should work faster
Yes. It is faster in 3 - 5 times !!!
And it processes XML file wo problem now also!!!

Many thanks.

Now I can use two scripts for different purposes
word: con‧ces‧sion‧aire
DIC2 sees this word as 4 different words. It is correct for some cases.
DIC1 sees this word as bad word and ignores. It is correct for some cases also.

Some wish:
Remove ask-dialog for ordered/don't ordered - it is complicated

Make pls (ordered/don't ordered) as parameter of call-script. (1/0 f.ex. default = 1) - without any dialog screens

Thanks for ALL.
Many wishes for ALL

SFC
Offline
Posts: 24
Joined: Sun Jul 12, 2015 9:37 am

Post by SFC »

very sorrrryy
Corections:
My pre- previous test was wrong
I tested scripts by absent dictionary = there was wrong path to dictionary.txt = there were tests without dictionary for both scripts

Now I test correctly both scripts:
file2 = 56,663,217 b = LDOCE6 xml code
DIC1 = 95000 - 96000 ms
DIC2 = 5500 - 6800 ms
That is right

conclusion is not altered

Many thanks
Locked