Итак есть тестовая переменная, в которой выражение предназначенное для того, чтобы перредать его функции eval. Одна беда, чилса в нем могут быть в виде
123,168.99
123'168.99
123 168,99
123168.99
123168,99 и т.д.
Надо написать код на jscript, который найдет все числа, правильно их распознает и приведет к виду 123168.99. На самом деле задача не однозначная, например 123,168 можно понять двумя способами, но в этом случае должно получиться 123.168. Вопрос как правильно такой код написать? Вроде начал писать регекспы, но больно уж запутано получается...
Здравствуйте, Рома Мик, Вы писали:
РМ>Итак есть тестовая переменная, в которой выражение предназначенное для того, чтобы перредать его функции eval. Одна беда, чилса в нем могут быть в виде РМ>123,168.99 РМ>123'168.99 РМ>123 168,99 РМ>123168.99 РМ>123168,99 РМ>и т.д. РМ>Надо написать код на jscript, который найдет все числа, правильно их распознает и приведет к виду 123168.99. На самом деле задача не однозначная, например 123,168 можно понять двумя способами, но в этом случае должно получиться 123.168. Вопрос как правильно такой код написать? Вроде начал писать регекспы, но больно уж запутано получается...
Если предположить что у чисел всегда будет дробная часть то примерно так (очень на вскидку):
на php (на js перепишешь сам надеюсь):
Здравствуйте, Рома Мик, не совсем понятны исходные данные. Какой тип тестовой переменной? Строка? Что она содержит? Строку, в тексте которой встречаются эти числа, или только псевдочисла по-отдельности? Что такое и т.п.? Какик еще могут быть варианты?
Re[2]: jscript: преобразовать числа к одному формату
Здравствуйте, virka, Вы писали:
V>Какой тип тестовой переменной? Строка?
Да, строка.
V>Что она содержит? Строку, в тексте которой встречаются эти числа,
Да. Причем это математическое выражение, т.е. кроме чисел там скорее всего встречаются только скобки и знаки арифметических операций, хотя я бы не стал на это полагаться.
V>Какик еще могут быть варианты?
([0-9]{1,3})?([,'` ][0-9]{3})*([\.,][0-9]*)?
Это очевидно неверное рег. выражение: как минимум (а) все символы разделители тысяч в одном числе одинаковые, (б) если уж запятая разделяет тысячи, то точка отделет дробную часть. Но смысл я думаю ясен.
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[3]: jscript: преобразовать числа к одному формату
Здравствуйте, Рома Мик, могу предложить такой вариант, не знаю, насколько он подойдет.
С рег.выражениями не сталкивался, так получилось, поэтому предлагаемый вариант без них.
Наверняка, есть гораздо более элегантное и мощное решение, Вам прийдется его поискать.
Предлагаемое решение исходит из таких допусков:
1. Знак пробела между числами означает разделитель одного числа, а не разделяет разные числа. В последнем случае нужно использовать хотя бы два символа пробела подряд.
2. Лишние пробелы в выражении убираются.
3. Число может иметь только два различных типа разделителя (например, 123,456,567.34 или 123'456'567,34 , а не 123,456'567.34)
4. При наличии двух различных типов разделителей последний преобразуется в точку, остальные отбрасываются.
5. При наличии в числе только одного разделителя он преобразуется в точку, если это запятая, в остальных случаях отбрасывается.
6. Выражения типа 67467jsdhfh8329 могут обрабатываться некорректно (в большинстве случаев остаются как есть).
//функция обработки чисел в строковом выражении
function convertNumberDot()
{
var src=arguments[0];//передаваемое выражение
var en=6;//максимальная степень чисел (т.е кол-во разделителей в числе 123 234 345 456 789.345 (в данном случае 5)
//вспомогательные переменные
var rez="";
var rezbr=new Array();
var tmp1, tmp2, tmp3, tmp4, tmp5;
var hlp1, hlp2, hlp3, hlp4;
var tmpcoa;
//
src=src.split("\r\n");//разбиваем выражение на строки
for(aco=0;aco<src.length;aco++)
{
tmp1=src[aco].split(" ");//разбиваем строку по пробелам
var rezar=new Array();
var passco=0;
for(bco=0;bco<tmp1.length;bco++)
{
tmp2=tmp1[bco];
if(tmp2!="")
{
tmp3=parseInt(tmp2);
hlp1=String(tmp3).length;
if(!isNaN(tmp3))//проверка на число
{
tmpcoa=bco;
for(cco=1;cco<en;cco++)//собираем число с разделителем в один пробел (глубина сборки определяется величиной en)
{
if(!isNaN(parseInt(tmp1[tmpcoa+cco])))//проверка на число следующего элемента
{
tmp2=tmp2+" "+tmp1[tmpcoa+cco];
bco++;
}
else{break;}
}//for(cco=1;cco<enum;cco++)
if(hlp1<tmp2.length)//если в числе присутствуют нечисловые элементы (предполагается, что разделители)
{
hlp2=tmp2.substring(hlp1,hlp1+1);//вырезание нечислового символа (предполагается, что разделителя)
tmp3=tmp2.split(hlp2);//разбивка по этому символу числа
tmp4=tmp3[tmp3.length-1];//последний элемент полученного массива
hlp1=String(tmp4).length;
hlp3=String(parseInt(tmp4)).length;
if((!isNaN(parseInt(tmp4)))&&(tmp4.substring(0,1)!=" "))//последний элемент число и не начинается с пробела (проверка)
{
if(hlp3<hlp1)//если этот последний элемент содержит другой нечисловой элемент (предполагается, что один), то он заменяется на символ "точка" (.)
{
hlp4=tmp4.substring(hlp3,hlp3+1);
tmp5=tmp4.split(hlp4);
(tmp5[1]=="")?(tmp4=tmp5.join("")):(tmp4=tmp5.join("."));//если второй разделитель — это последний символ, то он отбрасывается
tmp3[tmp3.length-1]=tmp4;
tmp2=tmp3.join("");
}//if(hlp3<hlp1)
else if((tmp3.length==2)&&(hlp2==","))//если нет, но разделитель один и это символ "запятая" (,), то он заменяется на символ "точка" (.)
{
tmp2=tmp3.join(".");
}//else if((tmp3.length==2)&&(hlp2==","))
else// в противном случае все разделители отбрасываются
{
tmp2=tmp3.join("");
}//else
}//if(!isNaN(tmp4))
}//if(hlp1<tmp2.length)
}//if(!isNaN(parseInt(tmp2)))
rezar[passco]=tmp2;
passco++;
}
}//for(bco=0;bco<tmp1.length;bco++)
rezbr[aco]=rezar.join(" ");// сборка строки
}//for(aco=0;aco<src.length;aco++)
rez=rezbr.join("\r\n");// сборка выражения по строкам
return rez;
}
Re[4]: jscript: преобразовать числа к одному формату
Спасибо за потраченные усилия. Но результат, что называется неверный, например:
222 444 +333,344.444 --> 222444+,44.444
Впрочем, если нет собственного интереса, то править ошибки не стоит, т.к. мне было интересно именно как правильно, т.е. с минимальными усилиями получить результат, в данном случае это очевидно регулярные выражения.
Re[4]: jscript: преобразовать числа к одному формату
За потраченные усилия благодарить не стоит, не было бы собств.желания и времени — не было б и усилий.
Делаю работу и немного "загрюз", захотелось развеяться.
По поводу предыдущего скрипта предполагалось, что выражения типа 123+234 будут писаться 123 + 234, в общем, все тонко и звонко.
Раз появилась такая возможность, немного поизучал рег.выражения, вот еще вариант.
Называется, "почуствуйте разницу", по объему и сложности скрипт конечно сильно сократился.
Не знаю, подойдет, такие условности:
1. Предполагается, что знак дроби — только точка "." или запятая ","
2. Все остальные разделители в числе сбрасываются.
3. Знак запятой, если один в числе — преобразуется в точку, если их больше одной — сбрасываются
4. Скрипт не имеет понятия о разделителях тысяч — т.е. он не ведет счет "на три", а обрабатывает все нечисловые элементы, окруженные числами.
5. Два числа, разделенные одним пробелом считаются одним числом, пробел отбрасывается.
6. Лишние пробелы не скидываются.
Функция —
//функция обработки чисел в строковом выражении
function convertNumberDot()
{
var src=arguments[0];//передаваемое выражение
//вспомогательные переменные
var rezar=new Array();
var rezbr=new Array();
//
var regexpnumb=/(\d+([,.'" ]\b)?)+|\D+/gi; //рег.выраж поиска чисел
var regexpdot=/\D+|\d+/gi; //рег.выраж поиска бяк в числах
rezar=src.match(regexpnumb); //разбиваем на массив "мухи отдельно, котлеты отдельно"
for(aco=0;aco<rezar.length;aco++)
{
if(!isNaN(parseInt(rezar[aco]))) //если муха
{
rezbr=rezar[aco].match(regexpdot);
if(rezbr!=null)
{
var boolfirst=true;
for(bco=rezbr.length-1;bco>=0;bco--)
{
if((isNaN(parseInt(rezbr[bco])))&&(rezbr[bco]!=rezar[aco].substring((rezar[aco].length-1),rezar[aco].length))) //первый с конца разделитель
{
if((boolfirst)&&((rezbr[bco]==",")||(rezbr[bco]=="."))) //если запятая или точка — ставим точку
{
rezbr[bco]=".";
boolfirst=false;
}//if((boolfirst)&&(rezbr[bco]==","))
else
{
rezbr[bco]=""; //в противном случае сбрасываем
}
}//if(rezbr[bco]!=rezar[aco].substring((rezar[aco].length-1),rezar[aco].length))
}//for(bco=rezbr.length-1;bco>=0;bco--)
}//if(rezbr!=null)
rezar[aco]=rezbr.join(""); //сборка
}//if(!isNaN(parseInt(rezar[aco])))
}//for(aco=0;aco<rez.length;aco+)
return rezar.join(""); //сборка и возврат
}
Исправил, но не на все случаи. Скрипт все усложняется.
Вариант 123,234 235,345 будет преобразован в 123.234 235.345 (скрипт посчитает разными числа 123.234 / 235.345)
но не вариант 123 345 456,458 345 (скрипт посчитает разными числа 123 / 345 / 456,458 / 345)
Все-таки на все случаи рецепта нет, какие-то правила нужно соблюдать.
Вообще-то я стараюсь не писать готовых скриптов (если не по работе), больше как в помощь (если получится) кому-нибудь изучать самому.
Последний вариант функции (если она Вам понадобится) можно найти на тестовой странице (просмотр HTML-кода).
Здравствуйте, Рома Мик, Вы писали:
РМ>Итак есть тестовая переменная, в которой выражение предназначенное для того, чтобы перредать его функции eval. Одна беда, чилса в нем могут быть в виде РМ>123,168.99 РМ>123'168.99 РМ>123 168,99 РМ>123168.99 РМ>123168,99 РМ>и т.д. РМ>Надо написать код на jscript, который найдет все числа, правильно их распознает и приведет к виду 123168.99. На самом деле задача не однозначная, например 123,168 можно понять двумя способами, но в этом случае должно получиться 123.168. Вопрос как правильно такой код написать? Вроде начал писать регекспы, но больно уж запутано получается...