我经常在数组或列表上使用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,但它没有提供解决方案。
答案 0 :(得分: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>
答案 1 :(得分:3)
你已经发现ColdFusion的数组循环实现存在缺陷:数组中的索引/位置根本不可用。
我raised this with Adobe,以及arrayEach()
功能中的类似失败。
关于Andrew Scott's blog的整个概念,有一些“有趣的”解读,其中讨论了各种意见(及其中的差异)。
顺便说一下, Railo 正确地完成了这一切,就像我在my own blog上写的那样。
最重要的是,你需要维护自己的计数器,并且@ Miguel-F确认。
投票给错误...也许Adobe会在ColdFusion 11中修复它们......
答案 2 :(得分:0)
让我尝试修复你的第二个例子,让它更具可读性......
<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>
答案 3 :(得分: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>');
}
如果我们认为cfloop的属性签名与使用for(counter;condition;incrementor)
与for(valuekey in object)
相同,我们会发现它们大致相同。
您可以选择如何迭代对象(数组),但不能选择仅值的版本,并让当前迭代器为您跟踪索引。
因此,如果您需要跟踪prev / next索引,则需要选择允许索引的迭代器方法(即使是手动完成)。
注意:对于数组,您可以将keyvalue与手动迭代器(for(k in obj)
样式)混合/匹配,但是当使用结构时,它是返回到'k'的实际KEY名称。不是迭代数组的值。这与在集合上循环的cfloop属性签名(例如:结构)一致。
我认为你要求cfloop让你设置一个值和索引属性标记。我意识到其他语言(和方言)可能会这样做,但到目前为止在CF,nope。
使用复合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)
当然,这只是按值查找索引,假设值是唯一的。使用其中一个使用索引的循环方法似乎更安全,而不是试图找出事后的位置。
答案 4 :(得分:0)
如果您使用的是CF 10或Railo 4,那么您可以使用each()中的Underscore.cfc library来循环索引:
_ = new Underscore();
_.each(myArray, function (value, index) {
// loop code here
});
我建议使用更具表现力的功能,例如map()或reduce(),具体取决于您尝试使用循环完成的内容。
注意:我写了Underscore.cfc