Форум » [x]Harbour » hb_hCaseMatch() в RU2151 » Ответить

hb_hCaseMatch() в RU2151

Haz: не понимаю как заставить хеш массив игнорировать регистр ключа . С латиницей работает отлично, но если ключ в кириллице , то никакие hb_hCaseMatch() не помогают. Может что еще нужно прописать чтоб нормально игнорировался регистр ? [pre2] 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 [/pre2] результат такой [pre2] ключ в верхний регистр ключ не найден ключ в нижний регистр тест пройден Press any key to continue... [/pre2] ключ в нижний регистр тест пройден

Ответов - 27, стр: 1 2 All

SergKis: Игорь, у тебя правильно реагирует, т.е. ты просишь исп. ключ "тест" в hash, как есть, т.е. hb_hCaseMatch( aHash, .F. ) и только такой ключ находится, остальные нет, т.е. для др. вариантов переводи ключ в upper (см. THmgData или используй)

Haz: SergKis пишет: Игорь, у тебя правильно реагирует, т.е. ты просишь исп. ключ "тест" в hash, как есть, т.е. hb_hCaseMatch( aHash, .F. ) я и hb_hCaseMatch( aHash, .T. ) пробовал тот же результат если ключ латиницей "test" , то находит и aHash['test'] и aHash['TEST'] нормально если ключ кириллицей "тест" то только строгое соответствие , вне зависимости от hb_hCaseMatch()

SergKis: Haz пишет если ключ кириллицей "тест" то только строгое соответствие , вне зависимости от hb_hCaseMatch() Столкнулся с таким поведением давно, потому сделал в THmgData переменную и танцую с ней (по возможности, свои ключи в EN, от пользователя ключи с ::lUpp := .T. и метод ниже), т.е. везде исп. THmgData, а не чистый hash METHOD Upp( Key ) INLINE iif( HB_ISCHAR( Key ) .AND. ::lUpp, Upper( Key ), Key )


Haz: SergKis пишет: Столкнулся с таким поведением давно, потому сделал в THmgData Понятно, значит косяк харбура. Придется прикручивать костыли. Спасибо Сергей.

Sergy: Сталкивался с такой-же ситуацией несколько лет назад с таки же эффектом. Разработчики Harbour ничего внятного не ответили. Региональные кодировки в case match не попадают и это действительно косяк. [pre]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[/pre]

SergKis: Sergy пишет Региональные кодировки в case match не попадают и это действительно косяк Не соглашусь, т.к. все зависит от цели применения. EN символы отрабатываются case match, языковые ключи как есть работают - понятный вариант. Если надо сохранить все ключи из базы (как написаны) - это один алгоритм Если надо группировать ключи (возможны варианты с ключами) - это другой Если вводите в GET и сразу в hash, то тоже возможны варианты ... Все на усмотрение программиста, INDEX на текстовые поля базы, как правило, в upper переводят, можно и через свои ф-ии и т.д.

Sergy: Примеры с "abc" и "ABC" работают, а "абв" и "АБВ" нет. Что это, если не косяк ? Если бы было заявлено, что "работает только с кодами ascii 0..127 - никаких вопросов. Но такого нет в описании, да и по отзывам в гуглоформе - с европейскими кодировками тоже все норм. Поэтому останусь при своем humble opininon. )) Понадобилось один раз, наступил на грабли, больше так не делаю.

SergKis: Sergy пишет Примеры с "abc" и "ABC" работают, а "абв" и "АБВ" нет. Что это, если не косяк ? Каким алгоритмом делать перевод в upper или lower в не зависящей от языка ф-ии поиска в hash, то что стоит RU1251 - это частный случай, а если нет языковой таблицы или не установлена а ключи hash используются. LV866 - такой языковой таблицы нет в windows от слова совсем (три языка), что и как должен работать поиск в hash не зная алгоритмов upper\lower Понадобилось один раз, наступил на грабли, больше так не делаю. Так это изучение предмета.

Sergy: 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() - поэтому "наши" кодовые страницы и глючат... ((

SergKis: Sergy пишет Посмотрел тут реализацию хэшей Посмотрите реализацию языков, там алгоритмы\таблицы соответствия для upper\lower, т.е. если нет реализации языка в hb, то нет и upper\lower алгоритмов, как, например, LV866. В версию unicode мы добавляем описание для LV866 сами, upper\lower работают, только по этой причине. Повторю, работа языкового ключа в hash, работает в значении как есть, т.е. ключ может быть установлен и найден в независимости от уст. языковой страницы, т.к. не делает перекодировку в upper\lower с повреждением ключа (от не верного или отсутствующего языка). Что разумно, по мне

Pasha: Haz пишет: hb_hSet( aHash, "тест", "тест пройден" ) ? "ключ в верхний регистр", if( hb_hHasKey(aHash, "ТЕСТ") , aHash["ТЕСТ"] , "ключ не найден" ) ? "ключ в нижний регистр", if( hb_hHasKey(aHash, "тест") , aHash["тест"] , "ключ не найден" ) если изменить первую строку на hb_hSet( aHash, "ТЕСТ", "тест пройден" ) то ключ на нижнем регистре находится Это конечно не решение, но хоть как-то..

Pasha: Посмотрел внимательнее код, и возник вопрос: а является ли харборовский хеш хешем ? Преобразования строки в хеш-значение не увидел. В функции hb_hashValuePtr, если значение не найдено, то ключ просто добавляется в хеш без всякого преобразования. А поиск выполняется методом половинного деления путем простого сравнения строк, если ключи символьные, ну или дат

Pasha: Pasha пишет: если изменить первую строку на hb_hSet( aHash, "ТЕСТ", "тест пройден" ) то ключ на нижнем регистре находится Это конечно не решение, но хоть как-то.. Извиняюсь, ошибся, так тоже не работает

Haz: SergKis пишет: в значении как есть, т.е. ключ может быть установлен и найден в независимости от уст. языковой страницы Сергей, потестировал различные кодовые страницы. Только в EN работает игнор регистра ключа. Любые значения "как есть" находит даже если страница не соответствует строке. Это скорее всего говорит о том , что где-то в алгоритмах хеша кодовая страница принудительно установлена на EN.и только в ней корректно работает Upper/Lower. Легко убедиться если при установленной EN вывести на экран UPPER / LOWER строки к примеру в кодировке 1251, она всегда будет выводиться "как есть". Думаю проблема где то рядом.

Pasha: Haz пишет: Сергей, потестировал различные кодовые страницы. Только в EN работает игнор регистра ключа. Любые значения "как есть" находит даже если страница не соответствует строке. Это скорее всего говорит о том , что где-то в алгоритмах хеша кодовая страница принудительно установлена на EN.и только в ней корректно работает Upper/Lower. Легко убедиться если при установленной EN вывести на экран UPPER / LOWER строки к примеру в кодировке 1251, она всегда будет выводиться "как есть". Думаю проблема где то рядом. Практически у всех, в том числе у русских, кодовых страниц установлен флаг HB_CDP_ACSORT_NONE. Ну а функция hb_itemStrICmp при сравнении строк при такой установке переводит в upper без учета кодовой страницы. Вот и получаем. Увы И да, харборовский хеш - это никакой не хеш, это просто отсортированный по ключам массив. Я такие отсортированные массивы использую еще с 90-х годов прошлого века, только хешем их не называю. Тоже увы.

Haz: Pasha пишет: hb_itemStrICmp при сравнении строк при такой установке переводит в upper без учета кодовой страницы. Вот и получаем. Увы Паша, спасибо за пояснения двойного "увы". Все стало ясно по использованию хеша. Мне в основном он нужен как переходник Hash <-> json , поиск по ключам в хеше удобнее, чем json строку парсить. Буду иметь ввиду, что если прилетит json с кючом в другом регистре будет ошибка. Придется делать дополнительные проверки через hb_JsonDecode( upper(json), @aHash )

SergKis: Haz пишет Придется делать дополнительные проверки через hb_JsonDecode( upper(json), @aHash ) В своей версии THmgData\TKeyData имею метод [pre2] 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 [/pre2]

Haz: SergKis пишет: В своей версии THmgData\TKeyData имею метод Логика понятна и вполне рабочая, ( делал почти так через hbclass() )есть маленькая неприятность с самим json. Вместе с Михаилом поупражнялся со строчками json различных api. Каких там только чудес нет. К примеру , значение ключа это массив , в котором еще массивы и вложенные json строки.. Чтобы найти ксе ключи нужно полностью распарстть всю строку или в рекурсии прогнать весь полученный хеш. Я пошел по пути второму, даже строится дерево хеша или массива , типа визуального просмотра. Из за перегруза пока бросил, но идея осталась следующая { 1 из json получить хеш 2 рекурсия по хешу и получение всех ключей, пути к ним и их значений. 3 тут как раз объектная модель представления хеш, . это полезно когда большая вложенность ключей и полный адрес значения получается не читаемый.Здесь каждый ключ представлен тремя сущностями - имя, путь и значение. 4 ну и сама обработка объектов. PS. попутно получил функцию просмотра хеша в стандартном дереве минигуи , с узлами и вложенностью, что в принципе удобно при отладке

SergKis: Haz пишет Каких там только чудес нет ... Чтобы найти ксе ключи нужно полностью распарстть всю строку или в рекурсии прогнать весь полученный хеш. Полностью согласен с выводами , т.к. надо самому по разному разобрать тексты с json, например, вставкой CRLF разбить на простые строки-элементы и построчно проводить обработку алгоритмами, определяя, что в строке json, массив или еще какая хрень. Выше показал ~ вариант только для 1-го пункта из списка, т.к. речь шла о hash и повторных ключах (у нас это не считается ошибкой, это, скорее, новое значение для ранее прошедшего ключа в разном написании)

SergKis: 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

Haz: SergKis пишет: json 5) Ну только разбором строки т.к. hb_jsonDecode() не понимает json 5 и , соответственно, хеш массив не сформирует.

SergKis: Haz пишет Ну только разбором строки Это 2-ой случай, когда дают таблицы в json 5, правда не сложные и пока обхожусь вариантом привода к json [pre2] j := SubS( J, At ("{", j) ) j := Left( J, RAt("}", j) ) j := left(j, 2)+'"'+subs(j, 3) j := StrTran(j, ":", '":') j := StrTran(j, ", ", ', "') j := StrTran(j, "'", '"') a := hb_jsonDecode(j) ? j ? "получена длинна массива:",len(a) получаем строку { "recid": 1, "fname": "John", "lname": "Doe", "email": "john@gmail.com", "profit": 2500, "sdate": "1/3/2012" } получена длинна массива: 6 [/pre2] Но если что то сложнее, то придется разбирать. Думал, что ты сталкивался, потому спросил.

Haz: SergKis пишет: Думал, что ты сталкивался, потому спросил. Сергей, так тут вариантов нет, только строку парсить. Сталкивался, при разборе скачанного HTML . К сожалению поддержки 5 версии в харбуре нет, все только строковыми операциями и каждый раз индивидуально.

Haz: SergKis пишет: Как обрабатываешь такие строки (json 5) ? Сергей, глянь здесь. Вдруг пригодится. https://github.com/imsys/JSON-ADVPL/blob/master/lib/JSON.prg

SergKis: Haz пишет глянь здесь Спасибо Попробовал взять строку json (из примера по ссылке) через hb_jsonDecode() : {"Products": [{"Name": "Water", "Cost": 1.3}, {"Name": "Bread", "Cost": 4e-1}], "Users": [{"Name": "Arthur", "Comment": "Hello\" \\World"}]} работает и без ф-ии из ссылки[pre2] j := hb_memoread(".\_c_.json") j := StrTran(j, '\"', "") j := StrTran(j, '\\', "") a := hb_jsonDecode(j) ? ".\_c_.json", a,"получена длинна массива:",len(a) for i:=1 to len(a) ? hb_hKeyAt(a,i),"=>",v:=hb_hValueAt(a,i),valtype(v) ? i, v for each m in v ? hb_valtoexp(m) next next ? результат Harbour MiniGUI Extended Edition 22.12.1 (32-bit) ANSI .\_c_.json HASH[2] получена длинна массива: 2 Products => ARRAY[2] A 1 ARRAY[2] {"Name"=>"Water", "Cost"=>1.3} {"Name"=>"Bread", "Cost"=>0.4} Users => ARRAY[1] A 2 ARRAY[1] {"Name"=>"Arthur", "Comment"=>"Hello World"} [/pre2]

Haz: SergKis пишет: Попробовал взять строку json (из примера по ссылке) ну так там , в отличии от твоей строки есть ключ массива и все ключи в массиве с кавычками. Можно приводить строку к "стандартному" виду, а можно функцию аналог hb_jsondecode() под себя подправить. Все зависит от того как часто и что приходится делать. Как показал мой опыт, этот путь бесконечен. Только вроде все сделал, и тут json с левой резьбой...

SergKis: Haz пишет Только вроде все сделал, и тут json с левой резьбой... На эту тему были мысли использовать php (к LetoDbf прикручивается) или js, но пока необходимости не было, json 5 -> json просто переводился.



полная версия страницы