EDIT:
Я подумал об этом и решил изменить его на фактический ответ. Поскольку вы используете CF2016 +, у вас есть доступ к некоторым из более современных функций, которые предлагает CF. Во-первых, Query of Query - отличный инструмент, но он может быть очень медленным. Особенно для меньшего количества записей. И затем, если в вашем базовом запросе много записей, это может поглотить память вашего сервера, поскольку это операция в памяти. Мы можем достичь нашей цели без необходимости QoQ.
Один из способов, которым мы можем подобрать дублирующуюся функциональность, которую вы ищете, - это использовать некоторые из новых функций CF. filter
, each
и sort
все работают с объектом запроса. Это версии member function
, но я думаю, что они выглядят чище. Кроме того, я использовал синтаксис cfscript.
В основном я использовал свой исходный запрос CFSCript (all_employees), который создает объект запроса, но я добавил к нему столбец f
, в котором содержится текст, по которому необходимо выполнить фильтрацию.
all_employees = QueryNew("userdefined,hello,f", "varchar,varchar,varchar",
[
["test","pure text","takeMe"],
["2","number as varchar","takeMe"],
["03","leading zero","takeMe"],
[" 4 ","leading and trailing spaces","takeMe"],
["5 ","extra trailing spaces","takeMe"],
[" 6","extra leading spaces","takeMe"],
["aasdfadsf","adsfasdfasd","dontTakeMe"],
["165e73","scientific notation","takeMe"],
["1.5","decimal","takeMe"],
["1,5","comma-delimited (or non-US decimal)","takeMe"],
["1.0","valid decimal","takeMe"],
["1.","invalid decimal","takeMe"],
["1,000","number with comma","takeMe"]
]
) ;
В исходном базовом запросе не было предложения WHERE
, поэтому дополнительная фильтрация исходных результатов не производилась. Но если бы нам было нужно, мы могли бы скопировать это с QueryFilter
или .filter
.
filt = all_employees.filter( function(whereclause){ return ( whereclause.f == "takeMe"); } ) ;
Это берет запрос all_employees
и применяет функцию, которая будет возвращать только те строки, которые соответствуют требованиям нашей функции. Так что любая строка запроса, где f == "takeMe"
. Это как WHERE f = 'takeMe'
в запросе. Это устанавливает новые отфильтрованные результаты в новый объект запроса filt
.
Затем мы можем использовать QueryEach
или .each
, чтобы пройти каждую строку нашего нового отфильтрованного запроса, чтобы изменить то, что нам нужно. В этом случае мы создаем новый массив для значений, которые мы хотим. for/in
цикл, вероятно, будет быстрее; Я не проверял.
filt.each(
function(r) {
retval.append(
ISNUMERIC(r.userDefined) ? right("00000000"<rim(rtrim((r.userdefined))),8) : r.userDefined
) ;
}
) ;
Теперь, когда у нас есть новый массив с желаемыми результатами, оригинальный QoQ хотел упорядочить эти результаты. Мы можем сделать это с ArraySort
или .sort
.
retval.sort("textnocase") ;
В моем тесте CF2016, похоже, прошел retval.sort()
как логическое значение и не вернул отсортированный массив, но CF2018 сделал. Это было ожидаемое поведение, так как тип возврата был изменен в CF2018. В любом случае, оба будут сортировать массив retval
, так что, когда мы выгрузим массив retval
, он будет в выбранном порядке.
И, как я всегда советую, загрузите тестирование в вашей системе с вашими данными. Как я уже сказал, это только один способ понять, что вы пытаетесь сделать. Есть и другие, которые могут быть быстрее.
https://cffiddle.org/app/file?filepath=dedd219b-6b27-451d-972a-7af75c25d897/54e5559a-b42e-4bf6-b19b-075bfd17bde2/67c0856d-bdb3-4c92-82ea-840e6b8b0214.cfm
(CF2018)> https://trycf.com/gist/2a3762dabf10ad695a925d2bc8e55b09/acf2018?theme=monokai
https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-m-r/queryfilter.html
https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-m-r/queryeach.html
https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-a-b/arraysort.html
ORIGINAL:
Это скорее комментарий, чем ответ, но он слишком длинный для комментария.
Я хотел бы упомянуть пару вещей, на которые стоит обратить внимание.
Во-первых, у ColdFusion isNumeric()
иногда могут быть неожиданные результаты. Это действительно не проверяет, является ли значение числом. Он проверяет, можно ли преобразовать строку в число. Таким образом, есть все виды значений, которые isNumeric()
будут видеть как numeric
. Пример: 1e3
- научная запись для 1000
. isNumeric("1e3")
вернет true
.
Мое второе предложение - как обращаться с начальным и конечным пробелом в «числовом» значении, например: " 4 "
. isNumeric()
вернет true
для этого, но когда вы добавите и обрежете свое окончательное значение, оно будет выглядеть как "000000 4"
. Мое предложение для решения этой проблемы - использовать val()
или ltrim(rtrim())
вокруг вашей колонки. val()
уменьшит его до базового числа (" 1.0 " >> "1"
), но ltrim(rtrim())
сохранит номер, но избавится от пробела (" 1.0 " >> "1.0"
), а также сохранит значение "научной нотации" (" 1e3 " >> "1e3"
). Оба по-прежнему пропускают 1,000
, поэтому, если это проблема, вам придется с этим справиться. Но используемый вами метод полностью зависит от значений, содержащихся в ваших данных. Проверка номера не всегда так проста, как кажется.
Я всегда был твердым сторонником GIGO - Garbage In, Garbage Out. Я считаю, что чистка основных данных является частью моей работы. Но если это будет экстремально или регулярно, я скажу источнику исправить это, или их вещи не будут работать правильно. Когда дело доходит до данных, невозможно учесть все возможности, но мы можем проверить общие ожидания. Белый список всегда легче, чем черный.
<cfscript>
all_employees = QueryNew("userdefined,hello", "varchar,varchar",
[
["test","pure text"],
["2","number as varchar"],
["03","leading zero"],
[" 4 ","leading and trailing spaces"],
["5 ","extra trailing spaces"],
[" 6","extra leading spaces"],
["165e73","scientific notation"],
["1.5","decimal"],
["1,5","comma-delimited (or non-US decimal)"],
["1.0","valid decimal"],
["1.","invalid decimal"],
["1,000","number with comma"]
]
)
//writedump(all_employees) ;
retval = [] ;
for (r in all_employees) {
retval.append(
{
"1 - RowInput" : r.userdefined.replace(" ","*","all") , // Replace space with * for output visibility.
"2 - IsNumeric?" : ISNUMERIC(r.userdefined) ,
"3 - FirstOutput": ( ISNUMERIC(r.userDefined) ? right("00000000"&r.userdefined,8) : r.userDefined ) ,
"4 - ValOutput" : ( ISNUMERIC(r.userDefined) ? right("00000000"&val(r.userdefined),8) : r.userDefined ) ,
"5 - TrimOutput" : ( ISNUMERIC(r.userDefined) ? right("00000000"<rim(rtrim((r.userdefined))),8) : r.userDefined )
}
) ;
}
writeDump(retval) ;
</cfscript>
https://trycf.com/gist/03164081321977462f8e9e4916476ed3/acf2018?theme=monokai