AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX Blogs
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 24.02.2010, 19:05   #1  
Blog bot is offline
Blog bot
Участник
 
25,475 / 846 (79) +++++++
Регистрация: 28.10.2006
Kashperuk Ivan: Casing and text search/comparison tutorial
Источник: http://kashperuk.blogspot.com/2010/0...omparison.html
==============

I have recently received a question from one of my blog readers.
He was asking about the possibility of doing case-sensitive search in AX.

I would like to reply to that by creating a small tutorial on search in AX. It is definitely not going to cover all the scenarios, but will give beginners a basic understanding of their options.

Download the tutorial xpo from my Skydrive

The tutorial consists of 1 form with 3 tab pages.

1.
Comparing two strings in AX is very simple: You can basically use the equality operator "==". As you can see from the tutorial, this is the case-insensitive operations, so "vanya" is equal to "Vanya".
AX also supports case-sensitive comparison. Kernel function strCmp() compares two strings taking into account the casing of the symbols in the string.

2.
Searching for a substring is a common operation in AX.
For that you have a number of options, as usual:
strScan() function ignores casing and allows you to specify from which position to search, and how many symbols. This is very basic, and a method like this is present in any programming language.
TextBuffer.find() is a more advanced use of the search mechanism. First of all, it allows to ignore or take into account the casing in the source text. Similar to strScan, it allows to specify the start position for the search.
What it also has is support for Regular Expressions, as well as the ability to, for example, paste the text to Windows clipboard.
Lastly, there is the match() function. The main purpose of it is to find a match based on the specified pattern using regular expressions, but nothing prevents using it for a simple search operation. It has a rather limited output though. You only get a boolean value stating whether a match was found or not, while with the previous 2 methods you also get the position of the substring.

Interesting
An interesting discovery that I made when writing the tutorial was about the speed of the different search operations. I have included this into the tutorial, so you can go in and try it yourself on your specific setup.
On my box, strScan() was the slowest operation of all, while TextBuffer, which I considered to be a very heavy class, was performing rather well.

Of course, single operation time compared to database operations is very low, so you won't notice it in your daily work. But it is something to think about.

3.
Finding a symbol in a string based on a specified set of symbols is also possible.
You have 2 functions at your disposal for that: strFind and strNFind. The difference is that strNFind searches for any symbol NOT present in the provided set, compared to strFind.


This is not an extensive list, so I would be interested in hearing which functions you use or what your results for performance comparison would be.


Источник: http://kashperuk.blogspot.com/2010/0...omparison.html
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору.
Старый 25.02.2010, 08:44   #2  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Еще про SysCompare напиши. Кстати, ссылку на твой блог уже в книжки вставляют - в "геттинг стартед" есть, которую я недавно оборзел, есть
Старый 25.02.2010, 11:19   #3  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
Цитата:
Сообщение от belugin Посмотреть сообщение
Еще про SysCompare напиши. Кстати, ссылку на твой блог уже в книжки вставляют - в "геттинг стартед" есть, которую я недавно оборзел, есть
Этот Packt Publishing. Капец.
Старый 25.02.2010, 11:30   #4  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
А про SysCompare я думал добавить, начал на него смотреть - полный трындец, а не код. mfp незачет
Да и вроде там нет public API для сравнения двух строк. Так что это решил упустить.
Старый 25.02.2010, 12:26   #5  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
\Classes\SysCompareText\run
правда имеет смысл только со много тросными строками.

А в чем капец в СисКолмпейр?
Старый 25.02.2010, 12:39   #6  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
Цитата:
Сообщение от belugin Посмотреть сообщение
\Classes\SysCompareText\run
правда имеет смысл только со много тросными строками.

А в чем капец в СисКолмпейр?

А, да, то есть АПИ таки есть.
Капец - да просто туча кода и фиг поймешь че делает. нечитаемо. один из методов:

X++:
/// <summary>
///    Fits records in the <c>ref</c> table so lines are only claimed one time.
/// </summary>
/// <remarks>
///    After this operation, lines may be claimed by several records if the lines appear in several
///    locations. In that case, one of the start positions and the length will be identical.
/// </remarks>
protected void fitRefs()
{
    //Fit all the shorter ones
    //and the ones overlapping with same length

    TmpCompareText ref2;
;

    //
    // Example:
    //
    // #1   1 -  5 ;  2 -  6   -> This is longer than #2 and is kept
    // #2   3 -  4 ; 10 - 11   -> This is shadowed by #1 and is deleted
    // #3   7 -  7 ; 14 - 14   -> #3 and #4 are identical, and decision is deferred to refCleanup()
    // #4   7 -  7 ; 20 - 20   -> #3 and #4 are identical, and decision is deferred to refCleanup()
    // #5  10 - 15 ; 25 - 30   -> This is longer than #6 and is kept
    // #6  17 - 20 ; 29 - 32   -> This is partly shadowed by #2, and is trimmed to: 19 - 20 ; 31 - 32
    //

    ref2.setTmpData(ref);
    while select ref
        order by Length desc, Text1Start
    {
        while select forupdate ref2
            where ref2.Length   <= ref.Length &&
                  ref2.RecId    != ref.RecId  &&
                   ((ref2.Text1Start >= ref.Text1Start && ref2.Text1Start  <= ref.Text1End)  ||
                    (ref2.Text1End   >= ref.Text1Start && ref2.Text1End    <= ref.Text1End)  ||
                    (ref2.Text2Start >= ref.Text2Start && ref2.Text2Start  <= ref.Text2End)  ||
                    (ref2.Text2End   >= ref.Text2Start && ref2.Text2End    <= ref.Text2End))
        {
            if ( ref2.Length   < ref.Length ||
                (ref2.Text1Start != ref.Text1Start &&
                 ref2.Text2Start != ref.Text2Start ))
            {
                if (ref2.Text1Start >= ref.Text1Start && ref2.Text1Start  <= ref.Text1End)       //Cut start of text1 in ref2
                {
                    ref2.Length     = ref2.Length     - (ref.Text1End + 1 - ref2.Text1Start);
                    ref2.Text2Start = ref2.Text2Start + (ref.Text1End + 1 - ref2.Text1Start);
                    ref2.Text1Start = ref.Text1End    + 1;
                    ref2.Text1End   = ref2.Text1Start + ref2.Length - 1;
                    ref2.Text2End   = ref2.Text2Start + ref2.Length - 1;
                }
                if (ref2.Text1End   >= ref.Text1Start && ref2.Text1End    <= ref.Text1End)       //Cut end of text1 in ref2
                {
                    ref2.Length     = ref2.Length    - (ref2.Text1End - (ref.Text1Start - 1));
                    ref2.Text2End   = ref2.Text2End  - (ref2.Text1End - (ref.Text1Start - 1));
                    ref2.Text1End   = ref.Text1Start - 1;
                    ref2.Text2Start = ref2.Text2End  - (ref2.Length - 1);
                    ref2.Text1Start = ref2.Text1End  - (ref2.Length - 1);
                }
                if (ref2.Text2Start >= ref.Text2Start && ref2.Text2Start  <= ref.Text2End)       //Cut start of text2 in ref2
                {
                    ref2.Length     = ref2.Length     - (ref.Text2End + 1 - ref2.Text2Start);
                    ref2.Text1Start = ref2.Text1Start + (ref.Text2End + 1 - ref2.Text2Start);
                    ref2.Text2Start = ref.Text2End    + 1;
                    ref2.Text2End   = ref2.Text2Start + ref2.Length - 1;
                    ref2.Text1End   = ref2.Text1Start + ref2.Length - 1;
                }
                if (ref2.Text2End   >= ref.Text2Start && ref2.Text2End    <= ref.Text2End)       //Cut end of text2 in ref2
                {
                    ref2.Length     = ref2.Length    - (ref2.Text2End - (ref.Text2Start - 1));
                    ref2.Text1End   = ref2.Text1End  - (ref2.Text2End - (ref.Text2Start - 1));
                    ref2.Text2End   = ref.Text2Start - 1;
                    ref2.Text1Start = ref2.Text1End  - (ref2.Length - 1);
                    ref2.Text2Start = ref2.Text2End  - (ref2.Length - 1);
                }

                if (ref2.Length <= 0)
                    ref2.delete();
                else
                    ref2.update();
            }
        }
    }
}
Да и сам метод run() в SysCompareText тоже, мягко говоря, не описан. Возвращаемый контейнер у меня состоял либо из 0 (если строки равны), либо из 1,2, если не равны. Причем я сперва подумал - круто, говорит, где именно ошибка. Но нет - просто возвращает 1,2 всегда
Старый 25.02.2010, 15:41   #7  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
0. по моему единственная претензия к куску кода - то, что написано комментами можно было написать названиями методов.Так проде там довольно обычный код по устранению пересечений интервалов
1. ты попробуй сравнить многострочные строки типа
X++:
<at>'мама 
мыла
раму'
<at>'мама 
сверлила
раму'
где AT это @

Последний раз редактировалось belugin; 25.02.2010 в 15:43.
 

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 23:01.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.