Модераторы: THandle, bems

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Заменить млн на нули 
:(
    Опции темы
Akella
  Дата 27.9.2011, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 7
Всего: 329



Обрабатываю текстовые объявления, в которых указана цена.
Цены могут быть так указаны:
2,3 млн
2.3 млн
5 млн
Ну в общем как податель объявы захочет.

Из текста регуляркой ищу цену, например, 2,3 млн.

Теперь цену нужно сохранить в базу, в поле типа float или integer, т.е. без млн.

Вот такой у мну алгоритм.

Код

Var
  m: string;
  p: double;
...
begin
...
// на входе 2,3 млн

      if pos('МЛН', AnsiUpperCase(m)) <> 0 then
        begin
          //меняем "." или "," на разделитель
          m := StringReplace(m, ',', DecimalSeparator, [rfReplaceAll, rfIgnoreCase]);
          m := StringReplace(m, '.', DecimalSeparator, [rfReplaceAll, rfIgnoreCase]);

          //получаем 2.3 млн

          m := OnlyDec(m, DecimalSeparator);// удаляем всё, кроме цифр и разделителя (моя функция), получаем 2.3

          p := StrToFloatDef(m, 0);// конвертируем в double, чтобы умножить на [I]1 000 000[/I]

          p := p * 1000000;// получаем [I]2 300 000[/I]

          m := FloatToStr(p);// возвращаем правильное число
        end;// if pos('МЛН', AnsiUpperCase(m)) <> 0 then


Но слишком замудрёно и, наверняка, не самый быстрый способ.

Может кто решал подобные проблемы и подскажет более правильный и быстрый код?
PM MAIL   Вверх
de_Nis
Дата 28.9.2011, 12:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Старательный
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 19.10.2006
Где: Молдова

Репутация: 1
Всего: 6



Уважаемый Akella! Может быть, этой теме место в основном форуме Дельфи? smile 
--------------------
Несчастлив не тот, у кого ничего нет, а тот, кто ничего не хочет…
PM   Вверх
Akella
Дата 28.9.2011, 12:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 7
Всего: 329



Здесь как бы уже решение решение. В принципе вопроса как бы и нету  smile , но как бы и есть. Нужна только оптимизация кода, если она поможет. А этот раздел как раз для таких случаев smile
PM MAIL   Вверх
kemiisto
Дата 28.9.2011, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дикий Кот. =^.^=
****
Награды: 1



Профиль
Группа: Участник Клуба
Сообщений: 3292
Регистрация: 29.7.2007

Репутация: 3
Всего: 160



Цитата(Akella @  27.9.2011,  21:32 Найти цитируемый пост)
Может кто решал подобные проблемы и подскажет более правильный и быстрый код? 

Группировки надо использовать в регулярке. Показывай свою регулярку.


--------------------
PM MAIL WWW GTalk Jabber   Вверх
Akella
Дата 28.9.2011, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 7
Всего: 329



какие группировки?
PM MAIL   Вверх
kemiisto
  Дата 28.9.2011, 23:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дикий Кот. =^.^=
****
Награды: 1



Профиль
Группа: Участник Клуба
Сообщений: 3292
Регистрация: 29.7.2007

Репутация: 3
Всего: 160



Akella, даже тут есть. Второй пример.


--------------------
PM MAIL WWW GTalk Jabber   Вверх
Keeper89
Дата 28.9.2011, 23:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: нет
Всего: 58





--------------------
PM MAIL WWW   Вверх
Akella
Дата 29.9.2011, 09:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 7
Всего: 329



Да при чём здесь регулярки, если мну нужно правильно заменить 2,3 млн или 10 млн на 2,300000 и соответственно на 10000000?

Добавлено через 22 секунды
Про группировку и скобки я в курсе если чё
PM MAIL   Вверх
Keeper89
Дата 30.9.2011, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: нет
Всего: 58



Akella:
Код

var
...
  IntP, FracP: Integer;
...
try
...
    RegExp.Expression := '(\d+)([.,])(\d+)';
    if RegExp.Exec('2,3 млн') then
    begin
      if TryStrToInt(RegExp.Match[1], IntP) and TryStrToInt(RegExp.Match[3], FracP) then  
        Result := FloatToStr(IntP * 1000000 + FracP * 100000);
    end
...

Как-то так, не тестировал. Но выглядит проще, чем твое.

Это сообщение отредактировал(а) Keeper89 - 30.9.2011, 14:37


--------------------
PM MAIL WWW   Вверх
Akella
Дата 30.9.2011, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 7
Всего: 329



Чем проще? Тем что я заменяю . или , на DecimalSeparator?

Ну и если у тебя попадётся какой-то мусор, то номер не пройдёт. А у меня этот мусор будет отсеян.
PM MAIL   Вверх
AndreyIQ
Дата 30.9.2011, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 185
Регистрация: 5.2.2007

Репутация: нет
Всего: 8



Цитата(Keeper89 @ 30.9.2011,  14:35)
Akella:
Код

var
...
  IntP, FracP: Integer;
...
try
...
    RegExp.Expression := '(\d+)([.,])(\d+)';
    if RegExp.Exec('2,3 млн') then
    begin
      if TryStrToInt(RegExp.Match[1], IntP) and TryStrToInt(RegExp.Match[3], FracP) then  
        Result := FloatToStr(IntP * 1000000 + FracP * 100000);
    end
...

Как-то так, не тестировал. Но выглядит проще, чем твое.

Интересно, что вернет Ваш код, если ввести 2,03 млн.
Цитата(Akella @ 27.9.2011,  22:32)
Обрабатываю текстовые объявления, в которых указана цена.
Но слишком замудрёно и, наверняка, не самый быстрый способ.

ИМХО проще некуда.
ЗЫ Что за код в OnlyDec?
PM MAIL   Вверх
CodeMonkey
Дата 30.9.2011, 21:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 4
Всего: 89



Может StringReplace 'млн' -> 'x10^6' ?

Тогда строка '2,3 млн.' после замены будет читаться как '2,3 x 10 ^ 6', что есть 2'300'000.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Keeper89
Дата 30.9.2011, 22:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: нет
Всего: 58



Цитата(AndreyIQ @  30.9.2011,  15:25 Найти цитируемый пост)
Интересно, что вернет Ваш код, если ввести 2,03 млн.


Цитата(Akella @  30.9.2011,  14:39 Найти цитируемый пост)
Чем проще? Тем что я заменяю . или , на DecimalSeparator?

Это дело корректировки регулярки.

Если надо вообще коротко (?), то можно сделать типа того, что CodeMonkey предложил.


--------------------
PM MAIL WWW   Вверх
Akella
Дата 1.10.2011, 11:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 7
Всего: 329



Цитата(CodeMonkey @ 30.9.2011,  21:14)
Может StringReplace 'млн' -> 'x10^6' ?

Тогда строка '2,3 млн.' после замены будет читаться как '2,3 x 10 ^ 6', что есть 2'300'000.

StringReplace не работает с цифрами или я не понял твоего примера.

Добавлено через 47 секунд
покажи пример на 5 млн, 10 млн и на 1.05 млн

Добавлено через 1 минуту и 37 секунд
Не забывайте, что это тексты объявлений и податель объявления может написать как ему моча в голову стукнет. Хот с точкой, хоть с запятой, хоть с двумя пробелами или без оных вообще. smile

Добавлено через 3 минуты и 12 секунд
Цитата(CodeMonkey @  30.9.2011,  21:14 Найти цитируемый пост)
'2,3 x 10 ^ 6',

Т.е. вот это потом перевести в число?
Код

i := StrToInt('2,3 x 10 ^ 6')

PM MAIL   Вверх
CodeMonkey
Дата 2.10.2011, 14:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 4
Всего: 89



Цитата
StringReplace не работает с цифрами или я не понял твоего примера.

Добавлено через 47 секунд
покажи пример на 5 млн, 10 млн и на 1.05 млн


Код
S := '.... бла-бла-бла... 5 млн руб. ... бла-бла-бла';

S := StringReplace(S, 'млн', 'x10^6', [rfReplaceAll, frIgnoreCase,frWholeWordsOnly {я придумал этот флаг}]);
S := StringReplace(S, 'тыс', 'x10^3', [rfReplaceAll, frIgnoreCase,frWholeWordsOnly]);

S := CleanStr(S); // удаляет ненужные символы, оставляя только цифры, точку, запятую, x и ^.

// S = '5x10^6'

S := StringReplace(S, '.', DecimalSeparator, [rfReplaceAll]);
S := StringReplace(S, ',', DecimalSeparator, [rfReplaceAll]);

I := Calc(S);

// I = 5'000'000


Цитата
Т.е. вот это потом перевести в число?
Код
i := StrToInt('2,3 x 10 ^ 6')


Ну да, но это почти не отличается от твоего исходного варианта в тексте вопроса. Только что тут разбор выражения будет выполнять интерпретатор (привет, LiveBindings smile ), а у тебя - фиксированный код.

В общем, смысл подхода, как я мыслю, сводится к замене узнаваемых слов (млн, миллионов, и т.п.) на числа (вернее - мат. выражения), затем вырезка всех лишних символов (пробелов и т.п.), после чего конвертация строки в число. 

Должно работать, если в коде предусмотрены все сокращения.

А в целом тут не столько от алгоритма зависит, сколько от его шлифовки под реальные данные.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi"
THandle

Добро пожаловать в форум группы "Delphi".

В разделе разрешается:

  • Флудить (в приемлемых величинах)
  • Обсуждать модерирование данного раздела (но не его модератора)
  • Добавлять свои правила если они не противоречат существующим
  • Делать наезды на пешеходов***

Строго запрещено:

  • Размещать рекламу
  • Совершать оскорбления личностей
  • Материться
  • *** Пешеходами не являются (ко)модераторы, админы, участники клуба.

Если Вам понравилась атмосфера форума, заходите к нам чаще! Люблю, целую, вечно Ваш, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Форум группы: delphi | Следующая тема »


 




[ Время генерации скрипта: 0.0760 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.