Ошибка неопределенного элемента при зацикливании массива с пустым значением - PullRequest
2 голосов
/ 21 марта 2011

Надеясь, что кто-то может дать мне представление о том, что я делаю неправильно.

Я зацикливаюсь на массиве и выдаю значения .... достаточно просто.Однако, если поле пустое, я получаю Element <VARIABLE> is undefined in <INDEX>.

Например,

<cfloop array="#allocationDetails.offerings#" index="myIndex">
#myIndex.name#
#myIndex.number#
#myIndex.somefield#
</cfloop>

. Это прекрасно работает, пока поле не имеет значения.Например, myIndex.somefield пусто, тогда я получаю сообщение об ошибке:

"Элемент somefield не определен в myIndex"

Если я оберну вывод поля в проверках, таких как isDefined ("myIndex.somefield ") или structKeyExists (myIndex," somefield ") и т. д., они возвращают true, но затем я получаю ошибку" Элемент somefield не определен в myIndex ", когда я пытаюсь вывести значение поля.

Я такжепопробовал cfdump на myIndex.somefield и получил ту же ошибку.

Я бы подумал, что это довольно простая вещь, но я не понимаю, почему возникает ошибка.Я упускаю что-то действительно очевидное?

Спасибо за вашу помощь.

Cheers Mark

Ответы [ 7 ]

4 голосов
/ 21 марта 2011

Может быть, для этого индекса нет элемента массива?Например:

<cfscript>
    myArr = ArrayNew(1);
    myArr[1] = 'xx';
    myArr[2] = 'yy';
    myArr[4] = 'zz';
</cfscript>

Если вы попытаетесь пройти через него, вы можете добавить проверку ArrayIsDefined:

<cfloop array="#myArr#" index="myIndex">
    <cfif ArrayIsDefined(myArr, myIndex)>
        #myIndex#
    </cfif> 
</cfloop>

Если нет, то всегда есть попытка catch:

<cfloop array="#myArr#" index="myIndex">
    <cftry>
        #myIndex#
        <cfcatch type="any">
            Error or default variable setting here
        </cfcatch>
    </cftry>
</cfloop>
1 голос
/ 21 марта 2011

Если вы используете ColdFusion 9, ошибка, которую вы получаете, связана с неопределенностью или значениями NULL, возвращаемыми из вызова веб-службы.Попробуйте вместо этого:

<cfif StructKeyExists(myIndex, "somefield") AND NOT IsNull(myIndex.somefield)>
    #myIndex.somefield#
</cfif>
1 голос
/ 21 марта 2011

Это полностью не проверено, но вы пробовали что-то подобное?

<cfloop array="#allocationDetails.offerings#" index="myIndex">
    <cfparam name="myIndex.name" default="" />
    <cfparam name="myIndex.number" default="" />
    <cfparam name="myIndex.somefield" default="" />
    #myIndex.name#
    #myIndex.number#
    #myIndex.somefield#
</cfloop>
0 голосов
/ 09 ноября 2012

Я делал что-то подобное. Я хотел среднее значение из массива, который может иметь неопределенные значения. Я наконец-то нашел два разных способа сделать это.

<cffunction name="ArrayAvg2">
  <cfargument name="theArray" required="true">
  <cfset sum=0>
  <blockquote>
  <cfloop from=1 to="#ArrayLen(theArray)#" index="i">
    <cfif ArrayIsDefined(theArray, i)>
      <cfoutput>theArray[#i#] = #theArray[i]#</cfoutput>
      <cfset sum += theArray[i]>
    <cfelse>
      Undefined
    </cfif>
    <br/>
  </cfloop>
  </blockquote>

  <cfreturn sum>
</cffunction>

<cffunction name="ArrayAvg3">
  <cfargument name="theArray" required="true">
  <cfset sum=0>
  <blockquote>
  <cfloop from=1 to="#ArrayLen(theArray)#" index="arrayElement">
    <cfif ArrayIsDefined(theArray, arrayElement)>
      <cfoutput>theArray[#arrayElement#] = #theArray[arrayElement]#</cfoutput>
      <cfset sum += theArray[arrayElement]>
    <cfelse>
      Undefined
    </cfif>
    <br/>
  </cfloop>
  </blockquote>

  <cfreturn sum>
</cffunction>

<cfset testArray=ArrayNew(1)>
<!--- no testArray[2] --->
<cfset testArray[1]=10>
<cfset testArray[3]=30>

testArray = <cfdump var="#testArray#">
<br/>
ArrayAvg2 = <cfdump var="#ArrayAvg2(testArray)#">
<br/>
ArrayAvg3 = <cfdump var="#ArrayAvg3(testArray)#">

Надеюсь, это поможет.

(Кстати, я новичок в ColdFusion, поэтому, если вы видите, что я делаю что-то не так, дайте мне знать!)

0 голосов
/ 22 марта 2011

Ого, это действительно меня смущает.

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

#StructKeyList(myIndex)#

Он выдает список доступных ключей в myIndex, который включает ВСЕ имена полей, как и ожидалось, включая поля, которые существуют, но являются пустыми.

При выполнении таких проверок, как StructKeyExists (myIndex, «somefield») или isDefined («myIndex.somefield»), возвращается значение true, поскольку ключ существует. Но если я тогда попытаюсь вывести поле myIndex.somefield, я получу поле Элемент some не определен в ошибке myIndex. Я не понимаю, почему это проблема. Я также пытался использовать, но это, похоже, ничего не делает (для моих массивов).

Если я попробую все предыдущие шаги на примере массива и зациклюсь, он будет работать как положено. Только когда я пытаюсь описать вышеизложенное с результатами веб-службы, у меня возникают проблемы.

Кто-нибудь видел эту проблему при работе с наборами записей веб-служб (на CF8)?

Теперь вернемся к обходным решениям…. Одно из предположений, которое работает (спасибо Ли), состоит в том, чтобы вместо использования myIndex.somefield вызывать метод getSomeField в веб-сервисе и использовать вместо него его результат (который работает, даже если значение пусто).

Другая вещь, которую я только что попробовал, которая также (по какой-либо причине) работает - это удаление имени индекса из isDefined, поэтому вместо:

isDefined(“myIndex.somefield”)

Я использую:

isDefined(“somefield”)

Опять же, похоже, это проблема, связанная с CF8, потому что, если я запускаю код на CF9 с использованием StructKeyExists, IsDefined или IsNull, все они работают как положено.

0 голосов
/ 21 марта 2011
<cfscript>
    allocationDetails.offerings = ArrayNew(1);
    allocationDetails.offerings[1] = {name = 'a', number = 1 , somefield = "somevalue"};
    allocationDetails.offerings[2] = {name = 'a', number = 2 , somefield = "somevalue"};
    allocationDetails.offerings[4] = {name = 'c', number = 3 , somefield = "somevalue"};
</cfscript>
<cfoutput>
<cfloop array="#allocationDetails.offerings#" index="myIndex">
    <cfparam name="myIndex.name" default="" />
    <cfparam name="myIndex.number" default="" />
    <cfparam name="myIndex.somefield" default="" />
    #myIndex.name# : #myIndex.number# :  #myIndex.somefield#<br>
</cfloop>
</cfoutput>

Решение Стива будет работать нормально.

0 голосов
/ 21 марта 2011

Сбросьте # allocDetails.offerings # и посмотрите результат.

Вы в основном зацикливаетесь на массиве. Таким образом, вы сможете увидеть результат каждого значения индекса.

Также может быть идиотским, но иногда это работает. Присвойте allocDetails.offerings переменной, а затем зациклите эту переменную.

<cfset some_var = allocationDetails.offerings />
<cfloop array="#some_var#" index="indexNow">
.
.
</cfloop>

Наконец, Также измените переменную индекса с myIndex на другое имя.

...