Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Пятничная задачка по regexp  [new]
Sergei.Agalakov
Member

Откуда:
Сообщений: 575
дано: 1,a,3,Z,5
получить: 5,Z,3,a,1
дано: 1,2,3,4,5,6,7,8
получить: 8,7,6,5,4,3,2,1
дано: 5,Z,0,q,1,b,A,Z
получить: Z,A,b,1,q,0,Z,5
т.е. получить обратный порядок слов в строке, используя regexp
(понятно что можно распарсить в таблицу и отсортировать).
Числа слов в строке неизвестно. В Google не смотреть. :^)
18 янв 08, 00:07    [5169024]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
Владимир Бегун
Member

Откуда: Redwood Shores, CA USA
Сообщений: 1707
Sergei.Agalakov
дано: 1,a,3,Z,5
получить: 5,Z,3,a,1
дано: 1,2,3,4,5,6,7,8
получить: 8,7,6,5,4,3,2,1
дано: 5,Z,0,q,1,b,A,Z
получить: Z,A,b,1,q,0,Z,5
т.е. получить обратный порядок слов в строке, используя regexp
(понятно что можно распарсить в таблицу и отсортировать).
Числа слов в строке неизвестно. В Google не смотреть. :^)

:-)

COLUMN o FORMAT A30
COLUMN r FORMAT A30
VAR s VARCHAR2(30)
EXEC :s := '5,Z,0,q,1,b,A,Z';

SET AUTOTRACE ON
  SELECT :s o
       , SUBSTR(SYS_CONNECT_BY_PATH(w, ','), 2) r
    FROM (
          SELECT MAX(LEVEL) OVER () ml
               , LEVEL l
               , REGEXP_SUBSTR(:s, '([^,])+', 1, LEVEL) w
            FROM dual
         CONNECT BY REGEXP_SUBSTR(:s, '([^,])+', 1, LEVEL) IS NOT NULL
         )
   WHERE LEVEL = ml
 CONNECT BY PRIOR l = l + 1
/
EXEC :s := ''
/
EXEC :s := '0'
/
Optionally, one could get it optimized to reduce the number of permutations.
18 янв 08, 05:00    [5169307]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
Владимир Бегун
Member

Откуда: Redwood Shores, CA USA
Сообщений: 1707
There is 10.2.0.3 bug that requires _optimizer_connect_by_cost_based to be set to FALSE, otherwise here is a bit more optimized version:
  SELECT :s o
       , SUBSTR(SYS_CONNECT_BY_PATH(w, ','), 2) r
    FROM (
          SELECT REGEXP_INSTR(:s, '([^,])+', 1, LEVEL) p
               , LEVEL l
               , REGEXP_SUBSTR(:s, '([^,])+', 1, LEVEL) w
            FROM dual
         CONNECT BY REGEXP_SUBSTR(:s, '([^,])+', 1, LEVEL) IS NOT NULL
         )
   WHERE CONNECT_BY_ISLEAF = 1
   START WITH REGEXP_INSTR(:s, ',([^,])+$', 1) + 1 = p
 CONNECT BY PRIOR l = l + 1
/
I could have used INSTR here for the START WITH predicate. Also in your particular case the regexp is not really needed.
18 янв 08, 05:47    [5169319]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
Владимир Бегун
Member

Откуда: Redwood Shores, CA USA
Сообщений: 1707
Here you can find a more elegant solution solving the task using just one hierarchical query.
18 янв 08, 08:42    [5169499]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
RA\/EN
Member

Откуда:
Сообщений: 3659
Sergei.Agalakov
дано: 1,a,3,Z,5
получить: 5,Z,3,a,1
дано: 1,2,3,4,5,6,7,8
получить: 8,7,6,5,4,3,2,1
дано: 5,Z,0,q,1,b,A,Z
получить: Z,A,b,1,q,0,Z,5
т.е. получить обратный порядок слов в строке, используя regexp
(понятно что можно распарсить в таблицу и отсортировать).
Числа слов в строке неизвестно. В Google не смотреть. :^)

На всех приведенных примерах отлично работает:
select reverse(:s) from dual
regexp прикручивать по вкусу
18 янв 08, 08:42    [5169500]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
Владимир Бегун
Member

Откуда: Redwood Shores, CA USA
Сообщений: 1707
RA\/EN
Sergei.Agalakov
дано: 1,a,3,Z,5
получить: 5,Z,3,a,1
дано: 1,2,3,4,5,6,7,8
получить: 8,7,6,5,4,3,2,1
дано: 5,Z,0,q,1,b,A,Z
получить: Z,A,b,1,q,0,Z,5
т.е. получить обратный порядок слов в строке, используя regexp
(понятно что можно распарсить в таблицу и отсортировать).
Числа слов в строке неизвестно. В Google не смотреть. :^)

На всех приведенных примерах отлично работает:
select reverse(:s) from dual
regexp прикручивать по вкусу
Reverse sucks.
18 янв 08, 08:46    [5169510]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
RA\/EN
Member

Откуда:
Сообщений: 3659
Sergei.Agalakov
(понятно что можно распарсить в таблицу и отсортировать).
Числа слов в строке неизвестно. В Google не смотреть. :^)

То, что это "понятно", трактовать как "[:|||||:] не предлагать" или как "покажите, как распарсить с помощью REGEXP"?
Владимир смог эту задачу аж 3 раза (за ночть ) разными способами, но в основе именно "распарсинг". Надо без него?
18 янв 08, 08:50    [5169520]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
RA\/EN
Member

Откуда:
Сообщений: 3659
Ну вот с моделькой (слегка убого, не силен я в них пока):
with q as (select '1,2,3,4,5,444,www' s from dual),
qq as(
select s,
       length(s)-length(regexp_replace(s,',',''))+1 ln
  from q),
qqq as (
select --+materialize
       *
  from qq
  model 
    return updated rows
    dimension by (0 rn)
    measures (cast(null as varchar2(4000)) as ss,qq.ln,qq.s)
    rules iterate (2000) until (ss[0] is not null)
    (ss[1]=case when iteration_number = 0 then null
                else ss[1]||regexp_substr(s[0],'\w+',1,ln[0]-iteration_number+2)||',' end,
     ss[0]=case when iteration_number=ln[0]+1 then iteration_number end))
select trim(both ',' from qqq.ss) from qqq where rn=1

TRIM(BOTH','FROMQQQ.SS)
--------------------------------------------------------------------------------
www,444,5,4,3,2,1
В очередной раз порадовал шибко умный оптимизатор - без материализации выдает:
select trim(both ',' from qqq.ss) from qqq where rn=1

ORA-01428: аргумент '0' вне диапазона
18 янв 08, 09:40    [5169675]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
Volder
Member

Откуда: Москва
Сообщений: 474
RA\/EN
Ну вот с моделькой (слегка убого, не силен я в них пока)
уменьшаем количество итераций, measures, правил:
SQL> with q as (select '1,2,3,4,5,444,www' s from dual)
  2  select part s, rtrim(str,',') reverse_s from q
  3   model
  4   partition by (s part)
  5   dimension by (0 dim)
  6   measures(s||',' str,nvl(length(regexp_replace(s,'[^,]')),0)+1 cnt)
  7    rules iterate (100) until (iteration_number+1=trunc(cnt[0]/2))
  8     (str[0]= regexp_replace(str[0],'^(([^,]+,){'||iteration_number||'})([^,]+,)(.*,)?([^,]+,)(([^,]+,){'||iteration_number||'})$','\1\5\4\3\6'))
  9  /

S                 REVERSE_S
----------------- ------------------
1,2,3,4,5,444,www www,444,5,4,3,2,1

SQL> 
18 янв 08, 12:43    [5171383]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
Евгений_25
Member

Откуда: Харьков
Сообщений: 460
Sergei.Agalakov
используя regexp


если нет 10-ки значит нет и пятничной задачки? :(
18 янв 08, 12:53    [5171482]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
Евгений_25
Sergei.Agalakov
используя regexp


если нет 10-ки значит нет и пятничной задачки? :(

отнюдь, имхо. :) Только на регулярусы плюньте слюной.
18 янв 08, 13:01    [5171553]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 18388
orawish
Евгений_25
Sergei.Agalakov
используя regexp
если нет 10-ки значит нет и пятничной задачки? :(

отнюдь, имхо. :) Только на регулярусы плюньте слюной.

Ну owa_pattern, положим, никто не отменял ;)
18 янв 08, 13:09    [5171644]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
with t as (select 'мама,мыла,раму,мылом' s from dual)
select max(substr(sys_connect_by_path(
                           substr(s,instr(','||s,',',-1,level)
                                   ,instr(s||',',',',-1,level)
                                   -instr(','||s,',',-1,level))
                          ,','),2))
  from t connect by level <= 1+length(s)-length(replace(s,','));
18 янв 08, 13:30    [5171871]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
RA\/EN
Member

Откуда:
Сообщений: 3659
Volder
RA\/EN
Ну вот с моделькой (слегка убого, не силен я в них пока)
уменьшаем количество итераций, measures, правил:
SQL> with q as (select '1,2,3,4,5,444,www' s from dual)
  2  select part s, rtrim(str,',') reverse_s from q
  3   model
  4   partition by (s part)
  5   dimension by (0 dim)
  6   measures(s||',' str,nvl(length(regexp_replace(s,'[^,]')),0)+1 cnt)
  7    rules iterate (100) until (iteration_number+1=trunc(cnt[0]/2))
  8     (str[0]= regexp_replace(str[0],'^(([^,]+,){'||iteration_number||'})([^,]+,)(.*,)?([^,]+,)(([^,]+,){'||iteration_number||'})$','\1\5\4\3\6'))
  9  /

S                 REVERSE_S
----------------- ------------------
1,2,3,4,5,444,www www,444,5,4,3,2,1

SQL> 


Медленнее и неправильно
1. rules iterate (100) - это значит, что для строки из 202+ слов результат будет некорректный.
2. На строке: lpad('1,2,3,',1000,'1,2,3,')||'3'
2.1. У меня: 0.3 секудны
2.2. У тебя: 11.4 секунды (это если поправить кол-во итераций на 500)

На строке из 3900 символов: мой SQL за 3.3 секудны, твой - (с поправленным количеством итераций) - 651 секунда
18 янв 08, 13:59    [5172161]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
RA\/EN
Member

Откуда:
Сообщений: 3659
orawish
with t as (select 'мама,мыла,раму,мылом' s from dual)
select max(substr(sys_connect_by_path(
                           substr(s,instr(','||s,',',-1,level)
                                   ,instr(s||',',',',-1,level)
                                   -instr(','||s,',',-1,level))
                          ,','),2))
  from t connect by level <= 1+length(s)-length(replace(s,','));

Чемпион по скорости, но где REGEXP?
P.S. Правда, все равно в 1500 раз медленнее, чем REVERSE
18 янв 08, 14:05    [5172208]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
RA\/EN
..
P.S. Правда, все равно в 1500 раз медленнее, чем REVERSE


не наблюдаю :)

Присоединен к:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

SQL> set timing on linesize 4000
SQL> with t as (select
  2  rpad('a',3999,',а,b,c,d,e,f,g,h,i,j') s
  3  , ',' d from dual)
  4  select substr(max(sys_connect_by_path(
  5           substr(s,instr(d||s,d,-1,level)
  6                   ,instr(s||d,d,-1,level)
  7                   -instr(d||s,d,-1,level))
  8         ,',')),2) r
  9    from t connect by level <= 1+length(s)-length(replace(s,d));

R
----------------------------------------------------------------------------------------------------
i,h,g,f,e,d,c,b,а,j,i,h,g,f,e,d,c,b,а,j,i,h,g,f,e,d,c,b,а,j,i,h,g,f,e,d,c,b,а,j,i,h,g,f,e,d,c,b,а,j,

Затрач.время: 00:00:00.08
SQL> 
SQL> with t as (select
  2  rpad('a',3999,',а,b,c,d,e,f,g,h,i,j') s
  3  , ',' d from dual)
  4  select reverse(s) r from t;

R
----------------------------------------------------------------------------------------------------
i,h,g,f,e,d,c,b,а,j,i,h,g,f,e,d,c,b,а,j,i,h,g,f,e,d,c,b,а,j,i,h,g,f,e,d,c,b,а,j,i,h,g,f,e,d,c,b,а,j,

Затрач.время: 00:00:00.03
18 янв 08, 14:19    [5172336]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
Elic
Member

Откуда:
Сообщений: 29990
RA\/EN
медленнее, чем REVERSE
Слова из одной буквы - это не слова
18 янв 08, 14:27    [5172396]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
Volder
Member

Откуда: Москва
Сообщений: 474
Костя,
RA\/EN
Медленнее и неправильно
1. rules iterate (100) - это значит, что для строки из 202+ слов результат будет некорректный.
ну про "неправильно" ты загнул :)) нули добавить в количество итераций не должно быть проблемой))
RA\/EN
2. На строке: lpad('1,2,3,',1000,'1,2,3,')||'3'
2.1. У меня: 0.3 секудны
2.2. У тебя: 11.4 секунды (это если поправить кол-во итераций на 500)
На строке из 3900 символов: мой SQL за 3.3 секудны, твой - (с поправленным количеством итераций) - 651 секунда
а вот это по делу
просто времени не было сравнить быстродействие

даже предполагаю из-за чего мой запрос слабоват - там маска в регексе меняется динамически на каждом шаге, для чего приходится ее заново анализировать
18 янв 08, 14:32    [5172435]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
Евгений_25
Member

Откуда: Харьков
Сообщений: 460
orawish
with t as (select 'мама,мыла,раму,мылом' s from dual)
select max(substr(sys_connect_by_path(
                           substr(s,instr(','||s,',',-1,level)
                                   ,instr(s||',',',',-1,level)
                                   -instr(','||s,',',-1,level))
                          ,','),2))
  from t connect by level <= 1+length(s)-length(replace(s,','));


ну вот - сходил пообедать :(
18 янв 08, 14:45    [5172531]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
Евгений_25
Member

Откуда: Харьков
Сообщений: 460
RA\/EN
P.S. Правда, все равно в 1500 раз медленнее, чем REVERSE


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


SELECT REVERSE(a) FROM (
SELECT max(sys_connect_by_path(LEVEL,',')) a FROM dual CONNECT BY LEVEL<100)

RES
-------------------------------------
99,89,79,69,59,49,39,29,19,09,98,88,78,68,58,48,38,28,18,08,97,87,77,67,57,47,37,27,17,07,96,86,76,66,56,46,36,26,16,06,95,85,75,65,55,45,35,25,15,05,94,84,74,64,54,44,34,24,14,04,93,83,73,63,53,43,33,23,13,03,92,82,72,62,52,42,32,22,12,02,91,81,71,61,51,41,31,21,11,01,9,8,7,6,5,4,3,2,1,
18 янв 08, 14:55    [5172614]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
RA\/EN
Member

Откуда:
Сообщений: 3659
orawish
RA\/EN
..
P.S. Правда, все равно в 1500 раз медленнее, чем REVERSE


не наблюдаю :)

Наблюдай правильно
SQL> set timing on
SQL> DECLARE
  2    v VARCHAR2(4000);
  3  BEGIN
  4    FOR i IN 1..150000 LOOP
  5    select reverse(lpad('1,2,3,',3900,'1,2,3,')||'3') s
  6      INTO v
  7      from dual;
  8    END LOOP;
  9  END;
 10  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:04.31
SQL> DECLARE
  2    v VARCHAR2(4000);
  3  BEGIN
  4    FOR i IN 1..100 LOOP
  5      with t as (select lpad('1,2,3,',3900,'1,2,3,')||'3' s from dual)
  6      select max(substr(sys_connect_by_path(
  7                                 substr(s,instr(','||s,',',-1,level)
  8                                         ,instr(s||',',',',-1,level)
  9                                         -instr(','||s,',',-1,level))
 10                                ,','),2))
 11        INTO v
 12        from t connect by level <= 1+length(s)-length(replace(s,','));
 13    END LOOP;
 14  END;
 15  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:04.84
SQL> select 150000/100 from dual;

150000/100                                                                      
----------                                                                      
      1500                                                                      

Elapsed: 00:00:00.01
18 янв 08, 16:44    [5173592]     Ответить | Цитировать Сообщить модератору
 Re: Пятничная задачка по regexp  [new]
RA\/EN
Member

Откуда:
Сообщений: 3659
Elic
RA\/EN
медленнее, чем REVERSE
Слова из одной буквы - это не слова

С философской точки зрения ты не прав - и система оплаты телеграфных сообщений это подтверждает
И вообще, с помощью REVERSE я ответил на три вопроса из четырех. Считаем:
  • (+)дано: 1,a,3,Z,5
    получить: 5,Z,3,a,1
  • (+)дано: 1,2,3,4,5,6,7,8
    получить: 8,7,6,5,4,3,2,1
  • (+)дано: 5,Z,0,q,1,b,A,Z
    получить: Z,A,b,1,q,0,Z,5
  • (+/-)т.е. получить обратный порядок слов в строке, используя regexp
  • 18 янв 08, 16:49    [5173650]     Ответить | Цитировать Сообщить модератору
     Re: Пятничная задачка по regexp  [new]
    Elic
    Member

    Откуда:
    Сообщений: 29990
    RA\/EN
    И вообще, с помощью REVERSE я ответил на три вопроса из четырех. Считаем:
    Никакая косноязычность вопрошающего не может умалить вины аппелирующего к "магичиским" исходным данным :)
    18 янв 08, 16:54    [5173697]     Ответить | Цитировать Сообщить модератору
     Re: Пятничная задачка по regexp  [new]
    orawish
    Member

    Откуда: Гадюкино-2 (City)
    Сообщений: 15487
    RA\/EN
    Наблюдай правильно

    алаверды (не в 1500 а в 6000 )

    set timing on
    DECLARE
      v VARCHAR2(4000);
    BEGIN
      FOR i IN 1..150000 LOOP
      select reverse(lpad(i,3900,'1,2,3,')||'3') s
        INTO v
        from dual;
      END LOOP;
    END;
    /
    
    DECLARE
      v VARCHAR2(4000);
    BEGIN
      FOR i IN 1..100 LOOP
        with t as (select lpad(i,3900,'1,2,3,')||'3' s from dual)
        select max(substr(sys_connect_by_path(
                                   substr(s,instr(','||s,',',-1,level)
                                           ,instr(s||',',',',-1,level)
                                           -instr(','||s,',',-1,level))
                                  ,','),2))
          INTO v
          from t connect by level <= 1+length(s)-length(replace(s,','));
      END LOOP;
    END;
    /

    на самом деле - иначе и быть не могло, помятуя о старике Шлемиэле
    18 янв 08, 17:23    [5173931]     Ответить | Цитировать Сообщить модератору
     Re: Пятничная задачка по regexp  [new]
    stax..
    Guest
    похожая тема
    (там, где реверс в шоколаде ;)

    ......
    stax
    18 янв 08, 17:47    [5174097]     Ответить | Цитировать Сообщить модератору
    Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
    Все форумы / Oracle Ответить