Автор | Сообщение |
|
| |
Пост N: 1865
Зарегистрирован: 20.02.11
|
|
Отправлено: 15.12.22 14:02. Заголовок: hb_hCaseMatch() в RU2151
не понимаю как заставить хеш массив игнорировать регистр ключа . С латиницей работает отлично, но если ключ в кириллице , то никакие hb_hCaseMatch() не помогают. Может что еще нужно прописать чтоб нормально игнорировался регистр ? func main() local aHash := hb_Hash() REQUEST HB_CODEPAGE_RU1251 hb_cdpSelect( "RU1251" ) hb_hCaseMatch( aHash, .F. ) hb_hSet( aHash, "тест", "тест пройден" ) ? "ключ в верхний регистр", if( hb_hHasKey(aHash, "ТЕСТ") , aHash["ТЕСТ"] , "ключ не найден" ) ? "ключ в нижний регистр", if( hb_hHasKey(aHash, "тест") , aHash["тест"] , "ключ не найден" ) wait return nil результат такой ключ в верхний регистр ключ не найден ключ в нижний регистр тест пройден Press any key to continue... ключ в нижний регистр тест пройден
|
|
|
Ответов - 27
, стр:
1
2
All
[только новые]
|
|
|
| постоянный участник
|
Пост N: 4182
Зарегистрирован: 17.02.12
|
|
Отправлено: 15.12.22 14:47. Заголовок: Игорь, у тебя правил..
Игорь, у тебя правильно реагирует, т.е. ты просишь исп. ключ "тест" в hash, как есть, т.е. hb_hCaseMatch( aHash, .F. ) и только такой ключ находится, остальные нет, т.е. для др. вариантов переводи ключ в upper (см. THmgData или используй)
|
|
|
|
| |
Пост N: 1866
Зарегистрирован: 20.02.11
|
|
Отправлено: 15.12.22 16:27. Заголовок: SergKis пишет: Игор..
SergKis пишет: цитата: | Игорь, у тебя правильно реагирует, т.е. ты просишь исп. ключ "тест" в hash, как есть, т.е. hb_hCaseMatch( aHash, .F. ) |
| я и hb_hCaseMatch( aHash, .T. ) пробовал тот же результат если ключ латиницей "test" , то находит и aHash['test'] и aHash['TEST'] нормально если ключ кириллицей "тест" то только строгое соответствие , вне зависимости от hb_hCaseMatch()
|
|
|
|
| постоянный участник
|
Пост N: 4183
Зарегистрирован: 17.02.12
|
|
Отправлено: 15.12.22 18:47. Заголовок: Haz пишет если ключ ..
Haz пишет цитата: | если ключ кириллицей "тест" то только строгое соответствие , вне зависимости от hb_hCaseMatch() |
| Столкнулся с таким поведением давно, потому сделал в THmgData переменную и танцую с ней (по возможности, свои ключи в EN, от пользователя ключи с ::lUpp := .T. и метод ниже), т.е. везде исп. THmgData, а не чистый hash METHOD Upp( Key ) INLINE iif( HB_ISCHAR( Key ) .AND. ::lUpp, Upper( Key ), Key )
|
|
|
|
| |
Пост N: 1867
Зарегистрирован: 20.02.11
|
|
Отправлено: 15.12.22 19:23. Заголовок: SergKis пишет: Стол..
SergKis пишет: цитата: | Столкнулся с таким поведением давно, потому сделал в THmgData |
| Понятно, значит косяк харбура. Придется прикручивать костыли. Спасибо Сергей.
|
|
|
|
| |
Пост N: 686
Зарегистрирован: 08.07.06
|
|
Отправлено: 16.12.22 19:17. Заголовок: Сталкивался с такой-..
Сталкивался с такой-же ситуацией несколько лет назад с таки же эффектом. Разработчики Harbour ничего внятного не ответили. Региональные кодировки в case match не попадают и это действительно косяк. FUNC Main() LOCAL h := { "abc" => 1, ; "Def" => 2, ; "GHI" => 3, ; "абв" => 4, ; "Где" => 5, ; "ЖЗИ" => 6 ; } REQUEST HB_LANG_RU REQUEST HB_CODEPAGE_RU866 hb_CDPSelect("RU866") hb_LangSelect("RU") hb_hCaseMatch(h, .F.) // ignore case ? "ABC =", h["ABC"] // 1 ? "DEF =", h["DEF"] // 2 ? "ghi =", h["ghi"] // 3 ? "АБВ =", h["АБВ"] // RTE: BASE/1132 - wrong array arguments ? "ГДЕ =", h["ГДЕ"] ? "жзи =", h["жзи"] RETURN NIL
|
|
|
|
| постоянный участник
|
Пост N: 4184
Зарегистрирован: 17.02.12
|
|
Отправлено: 16.12.22 19:57. Заголовок: Sergy пишет Регионал..
Sergy пишет цитата: | Региональные кодировки в case match не попадают и это действительно косяк |
| Не соглашусь, т.к. все зависит от цели применения. EN символы отрабатываются case match, языковые ключи как есть работают - понятный вариант. Если надо сохранить все ключи из базы (как написаны) - это один алгоритм Если надо группировать ключи (возможны варианты с ключами) - это другой Если вводите в GET и сразу в hash, то тоже возможны варианты ... Все на усмотрение программиста, INDEX на текстовые поля базы, как правило, в upper переводят, можно и через свои ф-ии и т.д.
|
|
|
|
| |
Пост N: 687
Зарегистрирован: 08.07.06
|
|
Отправлено: 16.12.22 20:09. Заголовок: Примеры с "abc..
Примеры с "abc" и "ABC" работают, а "абв" и "АБВ" нет. Что это, если не косяк ? Если бы было заявлено, что "работает только с кодами ascii 0..127 - никаких вопросов. Но такого нет в описании, да и по отзывам в гуглоформе - с европейскими кодировками тоже все норм. Поэтому останусь при своем humble opininon. )) Понадобилось один раз, наступил на грабли, больше так не делаю.
|
|
|
|
| постоянный участник
|
Пост N: 4185
Зарегистрирован: 17.02.12
|
|
Отправлено: 16.12.22 20:20. Заголовок: Sergy пишет Примеры ..
Sergy пишет цитата: | Примеры с "abc" и "ABC" работают, а "абв" и "АБВ" нет. Что это, если не косяк ? |
| Каким алгоритмом делать перевод в upper или lower в не зависящей от языка ф-ии поиска в hash, то что стоит RU1251 - это частный случай, а если нет языковой таблицы или не установлена а ключи hash используются. LV866 - такой языковой таблицы нет в windows от слова совсем (три языка), что и как должен работать поиск в hash не зная алгоритмов upper\lower цитата: | Понадобилось один раз, наступил на грабли, больше так не делаю. |
| Так это изучение предмета.
|
|
|
|
| |
Пост N: 688
Зарегистрирован: 08.07.06
|
|
Отправлено: 16.12.22 20:33. Заголовок: SergKis пишет: Каки..
SergKis пишет: цитата: | Каким алгоритмом делать перевод в upper или lower в не зависящей от языка ф-ии поиска в hash, то что стоит RU1251 - это частный случай, а если нет языковой таблицы или не установлена а ключи hash используются. LV866 - такой языковой таблицы нет в windows от слова совсем (три языка), что и как должен работать поиск в hash |
| Предположу, что точно таки-же, как и UPPER() / LOWER(). Ведь кодовая страница задана и они работают с латиницей и кириллицей одинаково, то должен работать и поиск ключей хэша - тоже одинаково. Посмотрел тут реализацию хэшей. Мало чего понимаю в Си, но уткнулся в модуле itemapi.c в функцию hb_itemStrICmp( PHB_ITEM pFirst, PHB_ITEM pSecond, HB_BOOL bForceExact ) - именно она вызывается, если игнорируется CaseMatch. ... /* Both strings not empty */ if( nMinLen ) { PHB_CODEPAGE cdp = hb_vmCDP(); if( cdp && ! HB_CDP_ISBINSORT( cdp ) ) iRet = hb_cdpicmp( szFirst, nLenFirst, szSecond, nLenSecond, cdp, bForceExact ); else { ... Запрос кодовой страницы идет. Но так понимаю, что где-то глубоко внутри движка Harbour не установлен HB_CDP_ISBINSORT() - поэтому "наши" кодовые страницы и глючат... ((
|
|
|
|
| постоянный участник
|
Пост N: 4186
Зарегистрирован: 17.02.12
|
|
Отправлено: 16.12.22 20:45. Заголовок: Sergy пишет Посмотре..
Sergy пишет цитата: | Посмотрел тут реализацию хэшей |
| Посмотрите реализацию языков, там алгоритмы\таблицы соответствия для upper\lower, т.е. если нет реализации языка в hb, то нет и upper\lower алгоритмов, как, например, LV866. В версию unicode мы добавляем описание для LV866 сами, upper\lower работают, только по этой причине. Повторю, работа языкового ключа в hash, работает в значении как есть, т.е. ключ может быть установлен и найден в независимости от уст. языковой страницы, т.к. не делает перекодировку в upper\lower с повреждением ключа (от не верного или отсутствующего языка). Что разумно, по мне
|
|
|
|
| Администратор
|
Пост N: 4102
Зарегистрирован: 23.05.05
|
|
Отправлено: 17.12.22 09:56. Заголовок: Haz пишет: h..
Haz пишет: цитата: | hb_hSet( aHash, "тест", "тест пройден" ) ? "ключ в верхний регистр", if( hb_hHasKey(aHash, "ТЕСТ") , aHash["ТЕСТ"] , "ключ не найден" ) ? "ключ в нижний регистр", if( hb_hHasKey(aHash, "тест") , aHash["тест"] , "ключ не найден" ) |
| если изменить первую строку на hb_hSet( aHash, "ТЕСТ", "тест пройден" ) то ключ на нижнем регистре находится Это конечно не решение, но хоть как-то..
|
|
|
|
|
| Администратор
|
Пост N: 4103
Зарегистрирован: 23.05.05
|
|
Отправлено: 17.12.22 10:27. Заголовок: Посмотрел внимательн..
Посмотрел внимательнее код, и возник вопрос: а является ли харборовский хеш хешем ? Преобразования строки в хеш-значение не увидел. В функции hb_hashValuePtr, если значение не найдено, то ключ просто добавляется в хеш без всякого преобразования. А поиск выполняется методом половинного деления путем простого сравнения строк, если ключи символьные, ну или дат
|
|
|
|
| Администратор
|
Пост N: 4104
Зарегистрирован: 23.05.05
|
|
Отправлено: 17.12.22 12:19. Заголовок: Pasha пишет: если и..
Pasha пишет: цитата: | если изменить первую строку на hb_hSet( aHash, "ТЕСТ", "тест пройден" ) то ключ на нижнем регистре находится Это конечно не решение, но хоть как-то.. |
| Извиняюсь, ошибся, так тоже не работает
|
|
|
|
| |
Пост N: 1868
Зарегистрирован: 20.02.11
|
|
Отправлено: 19.12.22 11:33. Заголовок: SergKis пишет: в зн..
SergKis пишет: цитата: | в значении как есть, т.е. ключ может быть установлен и найден в независимости от уст. языковой страницы |
| Сергей, потестировал различные кодовые страницы. Только в EN работает игнор регистра ключа. Любые значения "как есть" находит даже если страница не соответствует строке. Это скорее всего говорит о том , что где-то в алгоритмах хеша кодовая страница принудительно установлена на EN.и только в ней корректно работает Upper/Lower. Легко убедиться если при установленной EN вывести на экран UPPER / LOWER строки к примеру в кодировке 1251, она всегда будет выводиться "как есть". Думаю проблема где то рядом.
|
|
|
|
| Администратор
|
Пост N: 4105
Зарегистрирован: 23.05.05
|
|
Отправлено: 19.12.22 12:39. Заголовок: Haz пишет: Сергей, ..
Haz пишет: цитата: | Сергей, потестировал различные кодовые страницы. Только в EN работает игнор регистра ключа. Любые значения "как есть" находит даже если страница не соответствует строке. Это скорее всего говорит о том , что где-то в алгоритмах хеша кодовая страница принудительно установлена на EN.и только в ней корректно работает Upper/Lower. Легко убедиться если при установленной EN вывести на экран UPPER / LOWER строки к примеру в кодировке 1251, она всегда будет выводиться "как есть". Думаю проблема где то рядом. |
| Практически у всех, в том числе у русских, кодовых страниц установлен флаг HB_CDP_ACSORT_NONE. Ну а функция hb_itemStrICmp при сравнении строк при такой установке переводит в upper без учета кодовой страницы. Вот и получаем. Увы И да, харборовский хеш - это никакой не хеш, это просто отсортированный по ключам массив. Я такие отсортированные массивы использую еще с 90-х годов прошлого века, только хешем их не называю. Тоже увы.
|
|
|
|
| |
Пост N: 1869
Зарегистрирован: 20.02.11
|
|
Отправлено: 19.12.22 13:50. Заголовок: Pasha пишет: hb_it..
Pasha пишет: цитата: | hb_itemStrICmp при сравнении строк при такой установке переводит в upper без учета кодовой страницы. Вот и получаем. Увы |
| Паша, спасибо за пояснения двойного "увы". Все стало ясно по использованию хеша. Мне в основном он нужен как переходник Hash <-> json , поиск по ключам в хеше удобнее, чем json строку парсить. Буду иметь ввиду, что если прилетит json с кючом в другом регистре будет ошибка. Придется делать дополнительные проверки через hb_JsonDecode( upper(json), @aHash )
|
|
|
|
| постоянный участник
|
Пост N: 4187
Зарегистрирован: 17.02.12
|
|
Отправлено: 19.12.22 15:56. Заголовок: Haz пишет Придется д..
Haz пишет цитата: | Придется делать дополнительные проверки через hb_JsonDecode( upper(json), @aHash ) |
| В своей версии THmgData\TKeyData имею метод METHOD Json( cJson ) INLINE iif( HB_ISCHAR(cJson), ( cJson := SubStr( cJson, At ("{", cJson) ), ; cJson := Left( cJson, RAt("}", cJson) ), ; ::aKey := hb_jsonDecode( cJson ), Self ), ; hb_jsonEncode( ::aKey, .F. ) ) Работаю с ним так o := oHmgData() // oKeyData() cj := ... // строка json полученная o:Json(cj) // можно o:Set(hb_jsonDecode( cj )) FOR EACH a IN o:GetAll() ky := upper(a[1]) // ключ приводим к одному значению // тут подвод dbSeek или dbAppend REPL R_KY with ky, R_KEY with a[1], R_VAL with a[2] // условная команда NEXT
|
|
|
|
| |
Пост N: 1870
Зарегистрирован: 20.02.11
|
|
Отправлено: 20.12.22 11:11. Заголовок: SergKis пишет: В св..
SergKis пишет: цитата: | В своей версии THmgData\TKeyData имею метод |
| Логика понятна и вполне рабочая, ( делал почти так через hbclass() )есть маленькая неприятность с самим json. Вместе с Михаилом поупражнялся со строчками json различных api. Каких там только чудес нет. К примеру , значение ключа это массив , в котором еще массивы и вложенные json строки.. Чтобы найти ксе ключи нужно полностью распарстть всю строку или в рекурсии прогнать весь полученный хеш. Я пошел по пути второму, даже строится дерево хеша или массива , типа визуального просмотра. Из за перегруза пока бросил, но идея осталась следующая { 1 из json получить хеш 2 рекурсия по хешу и получение всех ключей, пути к ним и их значений. 3 тут как раз объектная модель представления хеш, . это полезно когда большая вложенность ключей и полный адрес значения получается не читаемый.Здесь каждый ключ представлен тремя сущностями - имя, путь и значение. 4 ну и сама обработка объектов. PS. попутно получил функцию просмотра хеша в стандартном дереве минигуи , с узлами и вложенностью, что в принципе удобно при отладке
|
|
|
|
| постоянный участник
|
Пост N: 4188
Зарегистрирован: 17.02.12
|
|
Отправлено: 20.12.22 11:33. Заголовок: Haz пишет Каких там ..
Haz пишет цитата: | Каких там только чудес нет ... Чтобы найти ксе ключи нужно полностью распарстть всю строку или в рекурсии прогнать весь полученный хеш. |
| Полностью согласен с выводами , т.к. надо самому по разному разобрать тексты с json, например, вставкой CRLF разбить на простые строки-элементы и построчно проводить обработку алгоритмами, определяя, что в строке json, массив или еще какая хрень. Выше показал ~ вариант только для 1-го пункта из списка, т.к. речь шла о hash и повторных ключах (у нас это не считается ошибкой, это, скорее, новое значение для ранее прошедшего ключа в разном написании)
|
|
|
|
| постоянный участник
|
Пост N: 4189
Зарегистрирован: 17.02.12
|
|
Отправлено: 20.12.22 17:08. Заголовок: Haz пишет Чтобы найт..
Haz пишет цитата: | Чтобы найти ксе ключи нужно полностью распарстть всю строку или в рекурсии прогнать весь полученный хеш. Я пошел по пути второму, даже строится дерево хеша или массива |
| Как обрабатываешь такие строки (json 5) ? j := [{ recid: 1, fname: 'John', lname: 'Doe', email: 'john@gmail.com', profit: 2500, sdate: '1/3/2012' }] a := hb_jsonDecode(J) ? "получена длинна массива:",len(a) дает результат: получена длинна массива: 0
|
|
|
Ответов - 27
, стр:
1
2
All
[только новые]
|
|