2

我经常在数组或列表上使用 cfloop,因为我有涉及数组值的复杂计算。但是,似乎没有办法引用数组/列表的特定成员。如果我使用普通循环,我可以很容易地做到这一点:

<cfloop from = "1" to = "#ArrayLen(myarray)#" index = "i">
<cfset temp = "myarray[i]">
<cfif mystruct[temp] GT 5>
  ... do something
</cfif>
<cfif myarray[i] NEQ myarray[i-1]>
  ...do something
</cfif>
</cfloop>

但是当我必须通过“i”而不是 i 处的值来引用它们时,涉及 myarray[i] 的计算可能会很麻烦。

但是如果我在数组上使用循环,我经常需要添加一个计数器:

<cfset m = 0>
<cfloop array = #myarray# index = "value">
<cfset m = m + 1>
<cfif mystruct[value] GT 5>
 ... do something
</cfif> 
<cfif myarray[i] NEQ myarray[i-1]>
  ...do something
</cfif>
</cfloop>

有谁知道如何在 cfloop array = myarray 编码中引用 myarray[i-1] ?在研究这个我发现这个咆哮: http: //www.markdrew.co.uk/blog/post.cfm/cfloop-rant,但它没有提供任何解决方案。

4

5 回答 5

3

以评论开头,但很快就变得太长了。正如你提到的,我通常使用计数器。我认为 ColdFusion 没有内置的方法可以为您处理这个问题。如果您只是担心将当前值与之前的值进行比较,我之前做过这样的事情:

<cfset previousValue = "">
<cfloop array = #myarray# index = "value">
    <cfif mystruct[value] GT 5>
        <!--- do something --->
    </cfif> 
    <cfif value NEQ previousValue>
        <!--- do something --->
    </cfif>
    <cfset previousValue = value>
</cfloop>
于 2013-06-13T18:01:37.893 回答
3

您已经发现 ColdFusion 的数组循环实现存在缺陷:数组中的索引/位置根本不可用。

我已经向 Adob​​e 提出了这个问题,并且该功能也出现了类似的失败arrayEach()

在Andrew Scott 的博客上对整个概念进行了一些“有趣的”阅读,其中讨论了各种观点(以及其中的差异)。

顺便说一句, Railo正确地完成了这一切,正如我在自己的博客上所写的那样。

最重要的是,您需要维护自己的柜台,正如您所暗示的那样,@Miguel-F 证实了这一点。

为错误投票...也许 Adob​​e 会在 ColdFusion 11 中修复它们...

于 2013-06-13T18:22:46.540 回答
1

让我尝试修复您的第二个示例并使其更具可读性...

<cfloop from="1" to="#ArrayLen(myarray)#" index="i">
  <cfset value = myarray[i]>
  <cfif mystruct[value] GT 5>
    ... do something
  </cfif>
  <cfset lastIndex = i - 1>
  <cfif lastIndex AND value NEQ myarray[lastIndex]>
    ... do something
  </cfif>
</cfloop>
于 2013-06-13T18:22:57.853 回答
0

让我们以不同的方式思考这个问题。如果我们出于说明目的在 cfscript 中重写这些:

  myArray=[ 'xyz', 'yyy', '232', 'uoiu', 'youneedthis', '2343'];
    writedump(myArray);
    myLongStringThing = '';

    // LOOP OVER AN INDEX AND MANUALLY PUSH YOUR ARRAY ALONG
    for ( i = 1; i <= myArray.size(); i++) {
      v = myArray[i];
      if(i < 5 && i > 1 && myArray[i] != myArray[i-1]   ){
        x = doSomethingComplicated(v);
        myArray[i] = x; // Your new computed value
      }

      if(i > 1 && v != myArray[i-1] ) {
        y = somethingElseCool(v);
        myLongStringThing &= y;
      }
    }

    writedump(myArray);
    writeoutput(myLongStringThing & '<br>');

    // LOOP THE VALUES IN THE STRUCT/ARRAY 
    i = 0;
    for (k in myArray) {
      i++;
      writeoutput('k:' & k & '<br>');
      writeoutput('a[i]:' & myArray[i] & '<br>');
    }

    function doSomethingComplicated(v) {
      Arguments.v &= 'you did it!';
      return Arguments.v;
}

    function somethingElseCool(v) {
      Arguments.v &= ';';
      return Arguments.v;
    }

    // LOOPING A STRUCT IS DIFFERENT
    myStruct = {'asdf' = 234234, 'sdfsd' = 9798, 'oiujlkj3' = 'kohjkjh'};
    for (k in myStruct) {
      writeoutput('kinstruct:' & k & '<br>');
      writeoutput('kinstruct:' & myStruct[k] & '<br>');
    }

for(counter;condition;incrementor)如果我们认为 cfloop 的属性签名与使用vs相同,for(valuekey in object)我们会发现它们大致相同。

您可以选择如何迭代您的对象(数组),但您不能选择仅值版本并让当前迭代器为您跟踪索引。

所以如果你需要跟踪你的上一个/下一个索引,你需要选择一个允许索引的迭代器方法(即使它是手动完成的)。

注意:对于数组,您可能可以将键值与手动迭代器(for(k in obj)样式)混合/匹配,但是当使用结构时,它是返回到“k”中的实际 KEY 名称。不是迭代数组的值。这与遍历集合(例如:结构)的 cfloop 属性签名一致。

我认为您要求 cfloop 让您同时设置值和索引属性标记。而且我意识到其他语言(和方言)可能会这样做,但到目前为止在 CF 中,没有。

使用复合 if 语句可以轻松管理边缘情况。

您也可以在标签中的 if 语句中使用完全相同的复合逻辑来解决边缘情况。

您可能已经注意到我使用size()ArrayLen(). 您可以在数组上使用一些 Java 运算符但是,据我所知,没有一个可以为您提供给定状态的“光标”或索引。

如果您想更深入地研究数组,可以创建数组的 java 版本并做更多的事情:

myArray = CreateObject( "java", "java.util.ArrayList" );
writeDump(myArray);  // This will show you the java object, which needs to be 'inited' still.
myArray = myArray.init(); // It returns the array, it does not act on the orig obj.
// You can now access the vast majority of java methods (including the parent methods)
myArray.add('myFirstValue');
myArray.add('my2ndValue');
myArray.add('yetAnotherValue');
writeDump(myArray);// This will look like a regular array dump
// You can also apply regular CF functions to this array like arrayAppend().
x = myArray.get(1); // This is a java index, so it begins at 0 which is the 1st elem. 1 is 2nd, etc.
writeOuput('At java index 1 we have:' & x & '<br>');

您可以使用其中的一些,但据我所知,它们都不会返回可用的光标或索引。不过有一些可能很方便,例如 subList() 和 equals()。

最终,如果您想在不保留手动索引的情况下找到索引,您可以这样做:

index = arrayFind(myArray, v)

当然,这只是按值查找索引,假设值是唯一的。使用其中一种使用索引的循环方法似乎更安全,而不是试图在事后弄清楚你在哪里。

于 2013-06-14T00:50:29.643 回答
0

如果您使用的是 CF 10 或 Railo 4,那么您可以使用Underscore.cfc 库中的each()循环使用索引:

_ = new Underscore();

_.each(myArray, function (value, index) {
   // loop code here
});

不过,我建议使用更具表现力的函数,例如map()reduce(),具体取决于您要通过循环完成的任务。

注意:我写了 Underscore.cfc

于 2013-06-16T16:33:17.607 回答