PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Сопоставление слов


Сопоставление слов

Сообщений 1 страница 21 из 21

1

Допустим есть некий набор слов (порядка 100 шт.) на иноземном
и набор этих слов в переводе на наш.
На вход поступает слово на ином. Надо вывести на нашем.

Чисто для примера:
pumpkin, pear, apple, plum, corn, cabbage ...
и перевод
тыква, груша, яблоко, слива, кукуруза, капуста ...

Я думаю так:

Код:
st1.s = "1pumpkin2pear3apple4plum5corn6cabbage"
st2.s = "тыква,груша,яблоко,слива,кукуруза,капуста"
f.s = "plum" ; перевести это слово
Debug StringField(st2, Val(Mid(st1, FindString(st1, f)-1, 1)), ",")

Или с одной строкой:

Код:
st.s = "тыква,груша,яблоко,слива,кукуруза,капуста,1pumpkin2pear3apple4plum5corn6cabbage"
f.s = "corn" ; перевести это слово
Debug StringField(st, Val(Mid(st, FindString(st, f, 44)-1, 1)), ",")

Предложите, пожалуйста, другой способ (более шустрый).

А может вот так?

Код:
st.s = "------ pumpkin.pear....apple...plum....corn....cabbage"
st1.s = "тыква,груша,яблоко,слива,кукуруза,капуста"
f.s = "apple" ; перевести это слово
Debug StringField(st1, FindString(st, f)/8, ",")

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

Отредактировано Andruk (27.02.2025 16:00:58)

0

2

А через JSON или Data(Various Topics ), структуру, List или Array, а быстрый поиск делать через Thread?

0

3

@ZOLO@ написал(а):

А через JSON или Data(Various Topics ), структуру, List или Array, а быстрый поиск делать через Thread?

Мне бы хоть какой-нибудь простой пример для познания, поскольку не искушен я в этих делах...

Отредактировано Andruk (27.02.2025 17:52:48)

0

4

Вот код изучай.
Код:
Procedure.s Find_Translation(stOriginal.s, stTranslation.s, stFindText.s)
  stReturn.s = "Нет найденого текста: "+stFindText
  If CountString(stOriginal, ":") = CountString(stTranslation, ":")
    For k = 1 To CountString(stOriginal, ":")+1
      If StringField(stOriginal, k, ":") = stFindText
        stReturn = StringField(stTranslation, k, ":")
        Break
      EndIf
    Next    
  Else
    stReturn = "Не совпали Original и Translation текс."
  EndIf
  ProcedureReturn stReturn
EndProcedure

st_ori.s = "pumpkin:pear:apple:plum:corn:cabbage"
st_per.s = "тыква:груша:яблоко:слива:кукуруза:капуста"
st_find.s = "cabbage"

Debug Find_Translation(st_ori, st_per.s, st_find.s)

0

5

Данные будут в строке в программе, не в наружных файлах? Дело в том что данных там может быть на несколько мегабайт и вводить их через запятую, мне кажется абсурдом. А если читать с наружного файла, там алгоритм совсем другой. Поэтому если дать алгоритм под строку, а потом выяснится что читаться будет из файла, то смысл тратить время на нерабочий вариант. StringField() работает неплохо для маленького списка, а для больших это будет жуткий тормоз. Можно было бы получить в массив SplitA2 и доступ к одинаковым словам по одинаковому индексу, но там тоже ReDim больше 1000 начнёт тормозить, надо писать код под задачу. Можно было бы сделать список структур с двумя полями - наверно наилучший вариант. Можно было бы сделать карту, но будет направленность перевода в одну сторону. С файла можно построчно читать, хотя построчно говорят работает медленно, лучше копировать в память, а потом распарсить данные методом посимвольного разбора.
Но чтобы всё это пробовать, надо знать как будут хранится данные, являются ли они в уже заложенном каком-то файла таким как словарь или же для них придумывается способ хранения.

Если хранить список в виде

яблоко|apple
дыня|melon

То можно методом FindString найти #LF$+яблоко| и прочитать текст от конца найденного до переноса строки #LF$ или наоборот найти |apple+#LF$, найти назад #LF$ и от него прочитать до "|". В таком случае парсить вообще не надо, но это будет работать медленнее, так как поиска по элементам списка будет прыгать на следующий элемент если первая буква не соответствует. В общем если разовый доступ, то лучше читать из файла, если частый доступ, то лучше заранее распарсить файл.

Также SplitListByWords как вариант.

Отредактировано AZJIO (27.02.2025 19:14:36)

0

6

Спасибо всем! Буду посмотреть.

Слов немного - около 100 шт. (специфические). Входящее  слово извне из файлов (множество раз). Перевод будет внесен в базу данных по этим файлам вместо аглицкого.

До ваших ответов у меня был еще такой вариант:

Код:
st1.s = "------ pumpkin.pear....apple...plum....corn....cabbage"
st2.s = "тыква,груша,яблоко,слива,кукуруза,капуста"
Dim Rus.s(6)
For k=1 To 6
 Rus(k) = StringField(st2, k, ",")
Next
f.s = "plum" ; перевести это слово
Debug Rus(FindString(st1, f)/8)

Но теперь буду смотреть другие способы. Спасибо!

Отредактировано Andruk (27.02.2025 20:02:26)

0

7

Вот еще код
Код:
Enumeration
  #pJSON
EndEnumeration

Structure FindTranslation
  stOriginal.s
  stTranslation.s
EndStructure

Procedure.s Find_Translation(List FindTranslation.FindTranslation(), stFindText.s)
  stReturn.s = "Нет найденого текста: "+stFindText
  
  If ListSize(FindTranslation()) = 0
    stReturn = "Нулевой лист."
  Else    
    ResetList(FindTranslation())
    ForEach FindTranslation()
      If FindTranslation()\stOriginal = stFindText
        stReturn = FindTranslation()\stTranslation
        Break
      EndIf
    Next
  EndIf
  ProcedureReturn stReturn
EndProcedure

;{ загружать через LoadJSON  
stOriginalTranslation.s =  "[ {"+Chr(34)+"stOriginal"+Chr(34)+":"+Chr(34)+"pumpkin"+Chr(34)+","+Chr(34)+"stTranslation"+Chr(34)+":"+Chr(34)+"тыква"+Chr(34)+"}, "+
                           "{"+Chr(34)+"stOriginal"+Chr(34)+":"+Chr(34)+"pear"+Chr(34)+","+Chr(34)+"stTranslation"+Chr(34)+":"+Chr(34)+"груша"+Chr(34)+"}, "+
                           "{"+Chr(34)+"stOriginal"+Chr(34)+":"+Chr(34)+"apple"+Chr(34)+","+Chr(34)+"stTranslation"+Chr(34)+":"+Chr(34)+"яблоко"+Chr(34)+"}, "+
                           "{"+Chr(34)+"stOriginal"+Chr(34)+":"+Chr(34)+"plum"+Chr(34)+","+Chr(34)+"stTranslation"+Chr(34)+":"+Chr(34)+"слива"+Chr(34)+"}, "+
                           "{"+Chr(34)+"stOriginal"+Chr(34)+":"+Chr(34)+"corn"+Chr(34)+","+Chr(34)+"stTranslation"+Chr(34)+":"+Chr(34)+"кукуруза"+Chr(34)+"}, "+
                           "{"+Chr(34)+"stOriginal"+Chr(34)+":"+Chr(34)+"cabbage"+Chr(34)+","+Chr(34)+"stTranslation"+Chr(34)+":"+Chr(34)+"капуста"+Chr(34)+"} ]"
;}

If ParseJSON(#pJSON, stOriginalTranslation) ; заменяется на LoadJSON  
  NewList FindTranslation.FindTranslation()
  ExtractJSONList(JSONValue(#pJSON), FindTranslation())
  st_find.s = "plum"
  Debug Find_Translation(FindTranslation(), st_find)
  FreeList(FindTranslation())
  FreeJSON(#pJSON)
Else
  Debug JSONErrorMessage()
EndIf

Загружай все слова в JSON и через структуру и List или Array, Map.

0

8

@ZOLO@ написал(а):

Загружай все слова в JSON и через структуру и List или Array, Map.

С JSON еще не сталкивался - надо будет почитать. Спасибо.
А вот предыдущий ваш пример, сдается мне, быстрее не будет. Я не оформлял код в рабочую процедуру - просто искал подходящий алгоритм.

0

9

Andruk написал(а):

А вот предыдущий ваш пример, сдается мне, быстрее не будет. Я не оформлял код в рабочую процедуру - просто искал подходящий алгоритм.

будит если использовать Thread.

0

10

@ZOLO@ написал(а):

будит если использовать Thread.

До Thread-а мне еще далеко... Я еще во многом собак не ел. Наверняка вы правы.

0

11

Ну если 100 слов, тогда можно так:

Код:
;- TOP
EnableExplicit

Structure Dictionary
	en.s
	ru.s
EndStructure

Procedure SplitL3(String1.s, String2.s, List StringList.Dictionary(), Separator.s = ",")
	Protected S1.String, *S1.Integer = @S1
	Protected S2.String, *S2.Integer = @S2
	Protected.i p, slen
	slen = Len(Separator)
	ClearList(StringList())

	*S1\i = @String1
	Repeat
    AddElement(StringList())
    p = FindString(S1\s, Separator)
    StringList()\en = PeekS(*S1\i, p - 1)
    *S1\i + (p + slen - 1) << #PB_Compiler_Unicode
	Until p = 0
	*S1\i = 0

	*S2\i = @String2
	ResetList(StringList())
	While NextElement(StringList())
    p = FindString(S2\s, Separator)
    StringList()\ru = PeekS(*S2\i, p - 1)
    *S2\i + (p + slen - 1) << #PB_Compiler_Unicode
    If p = 0
    	Break
    EndIf
	Wend
	*S2\i = 0

EndProcedure

Procedure IsLatin(*c.Character)
    Protected flag = #True

    If *c = 0 Or *c\c = 0
        ProcedureReturn 0
    EndIf

    Repeat
;         If Not ((*c\c >= '0' And *c\c <= '9') Or (*c\c >= 'a' And *c\c <= 'z') Or (*c\c >= 'A' And *c\c <= 'Z') Or *c\c = '_')
        If Not ((*c\c >= 'a' And *c\c <= 'z') Or (*c\c >= 'A' And *c\c <= 'Z') Or *c\c = '`')
            flag = #False
            Break
        EndIf
        *c + SizeOf(Character)
    Until Not *c\c

    ProcedureReturn flag
EndProcedure

;- ● Define
Define st1.s, st2.s, f.s
st1 = "pumpkin,pear,apple,plum,corn,cabbage"
st2 = "тыква,груша,яблоко,слива,кукуруза,капуста"


Define NewList Dictionary.Dictionary()
If CountString(st1, ",") = CountString(st1, ",")
	SplitL3(st1, st2, Dictionary(), ",")
Else
	MessageRequester("Ошибка", "нет одинаковости числа элементов в строках")
	End
; 	Debug "нет одинаковости числа элементов в строках"
EndIf
; ForEach Dictionary()
;     Debug Dictionary()\en
;     Debug Dictionary()\ru
; Next

;- # Constants
#Window = 0
Enumeration
	#inp
	#btn
	#StatusBar
EndEnumeration


;-┌──GUI──┐
If OpenWindow(#Window, 0, 0, 220, 100, "Переводчик", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
; 	StringGadget(#inp, 10, 10, 206, 30, "plum")
	ComboBoxGadget(#inp, 10, 10, 206, 30)
	ForEach Dictionary()
    AddGadgetItem(#inp, -1, Dictionary()\en)
	Next
	ForEach Dictionary()
    AddGadgetItem(#inp, -1, Dictionary()\ru)
	Next
	SetGadgetState(#inp, 0)
	ButtonGadget(#btn, 10, 50, 99, 30, "Проверить")
	TextGadget(#StatusBar, 115, 50, 100, 30, "", #PB_Text_Border)
	
;-┌──Loop──┐
	Repeat
    Select WaitWindowEvent()
    	Case #PB_Event_Gadget
        Select EventGadget()
        	Case #btn
            f = GetGadgetText(#inp)
            If Asc(f)
            	If IsLatin(@f)
                ForEach Dictionary()
                	If Dictionary()\en = f
;                     Debug Dictionary()\ru
                    SetGadgetText(#StatusBar, Dictionary()\ru)
                    Break
                	EndIf
                Next
            	Else
                ForEach Dictionary()
                	If Dictionary()\ru = f
;                     Debug Dictionary()\en
                    SetGadgetText(#StatusBar, Dictionary()\en)
                    Break
                	EndIf
                Next
            	EndIf
            EndIf
        EndSelect
    	Case #PB_Event_CloseWindow
        CloseWindow(#Window)
        End
    EndSelect
	ForEver
EndIf
;-└──Loop──┘

А вот тут имеет смысл использовать функцию IsLatin, чтобы определить язык строки и выбрать правильное направление перевода.

Отредактировано AZJIO (27.02.2025 20:45:38)

0

12

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

0

13

Код:
NewMap EngRusDic.s()
EngRusDic("pumpkin") = "тыква"
EngRusDic("pear") = "груша"
EngRusDic("apple") = "яблоко"
EngRusDic("plum") = "слива"
EngRusDic("corn") = "кукуруза"
EngRusDic("cabbage ") = "капуста "
Debug EngRusDic("pear")

так не?

+1

14

Lin написал(а):

так не?

М-да... Чевой-то я до карт не допёр... Это потому что при своем мизерном опыте ни разу не приходилось использовать.
Зачем только головы людям морочил?
Действительно, кажись так будет лучше всего.
Премного вам благодарен!!

0

15

Если вам нужно конкретное сопоставление, просто перевод одной строки в другую, используйте хэш-карту, Lin это показал. Это будет достаточно быстро.

0

16

И при том что карту я тоже предлагал...

0

17

Интересно, что, я сейчас загрузил пост, а у меня последнее сообщение от Lin Но, после отправки своего сообщения, увидел что автор поста, написал гораздо раньше меня. Ох уж этот CDN...

0

18

AZJIO написал(а):

И при том что карту я тоже предлагал...

Точно. Вот только как-то промелькнуло мимо сознания...
Пока конкретно носом не ткнули.

Отредактировано Andruk (01.03.2025 12:38:38)

0

19

в данном случае при таком количестве карта самый удобный вариант, но самый тормознутый
карты медленные из-за ключа, он то строковый, а строка это всегда долго

самое быстрое что придумал для одной из прог с 200 000 строк
давно было, толком не помню, так что сам смысл ускорения поиска в большом списке
на старте весь список проходится один раз, собирая в массив или в карту, не помню, адреса первой и последней строк на текущую букву
при поиске ищем только на эту букву
на сколько вырастает скорость поиска сами считайте, моя прога летает, реально поиск идёт по мере ввода на лету
автор этого листинга говорил что не получится, будет сильный тормоз, он ошибся
если список совсем большой, можно внутри буквы ещё поделить по две буквы тем же образом

0

20

newJS написал(а):

карты медленные из-за ключа, он то строковый, а строка это всегда долго

неа, он воспринимает их как бинарный ключ, и вроде даже создаёт хеш для быстрого доступа. Именно из-за того что доступ мгновенный можно понять что это не строки. Поднималась тема создать карту из чисел, не значение, а именно ключ, якобы это бы ускорило карту зная что число данных не превысит максимальное значение например типа q или l, но при этом ключ будет иметь постоянную ширину и не будет требовать получать хеши строк. Но паровоз так и не сдвинулся.

newJS написал(а):

при поиске ищем только на эту букву

так это же алгоритм "Radix Tree", но только не для одной и не для двух букв, а для всех, последние цепочки, у которых нет вариаций попадают в дерево целиком.

Отредактировано AZJIO (02.03.2025 08:24:03)

0

21

AZJIO написал(а):

так это же алгоритм "Radix Tree"

не знаю что это такое, для своей проги сам придумал
своё всегда понятней и сделано под конкретную задачу

AZJIO написал(а):

неа, он воспринимает их как бинарный ключ

карты медленней листа и массива

AZJIO написал(а):

и вроде даже создаёт хеш для быстрого доступа

тоже не уверен, но кажется ключи просто перебираются пока не найдёт
быстрее не писать всегда ключ, а использовать активный элемент

0


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Сопоставление слов