Reputation: 28513
I'm still trying to get my grips on Coldfusion...
I need to create a directy of files (say there are 10 files) and output 5 random files. Getting and outputting files is ok, but I'm not sure where to fit in the randrange. Here is my code:
<cfdirectory action="list" directory="#expandpath("img/")#" filter="some*.*" name="dir">
<!--- imgID --->
<CFSET imgID= #RandRange(1, #dir.allRecords#)#>
<!--- this only grabs the first 5 files --->
<cfoutput query="dir" maxrows="5">
<cfif FileExists("#expandpath("img/#name#")#")>
<cfimage source="#expandpath("img/#name#")#" name="myImage"> <cfif IsImage(myImage) is true>
<cfset ImageSetAntialiasing(myImage,"on")>
<cfset ImageScaleToFit(myImage,"highestQuality")>
<!--- append to a list --->
<li><cfimage source="#myImage#" action="writeToBrowser"></li>
</cfif>
</cfif>
</cfoutput>
This works ok in displaying the first 5 images. However, I would like to have 5 random images.
Thanks for some insights!
EDIT:
This is how I ended up doing it - ONE QUESTION UNSOLVED -
<!-- get the directy, listinfo="name" because I only need filenames --->
<cfdirectory action="list" LISTINFO="name" directory="#expandpath(" logos/")#" filter="marke*.*" name="dir">
<cfset images=[ ]>
<!-- since dir is not indexable, like dir[pos], I need another array!-->
<cfset dirArr=[ ]>
<cfset blocker="false">
<cfset maxLogos=5>
<!-- fill new dirArr(ay) -->
<cfoutput query="dir">
<cfset #ArrayAppend(dirArr, #expandpath( "logos/#name#")#)#>
</cfoutput>
<!-- loop -->
<cfloop condition="blocker eq false">
<-- random position -->
<cfset pos=R andRange(1, #dir.recordcount#)>
<cfif #dir.recordcount# eq 0 OR #ArrayLen(images)# gte #maxLogos#>
<-- STOP loop -->
<cfset blocker="true">
</cfif>
<cfset ArrayAppend(images, #dirArr[pos]#)>
<!-- BROKEN unknown ARRAYDELETE -->
<!--- <cfset ArrayDelete(dirArr, #dirArr[pos]#)> --->
<!-- IMG -->
<cfimage source="#dirArr[pos]#" name="myImage">
<cfif IsImage(myImage) is true>
<cfoutput>
<li data-icon="false">
<cfimage source="#myImage#" action="writeToBrowser">
</li>
</cfoutput>
</cfif>
</cfloop>
The problem is the ArrayDelete does not work variable ARRAYDELETE is undefined, Coldfusion(8) tells me. Any idea what I'm doing wrong?
Upvotes: 1
Views: 1075
Reputation: 112190
A simple alternative is to shuffle the array once and then take the first five items:
<cfset MaxLogos = 5 />
<cfset Images = [] />
<cfset Files = DirectoryList( expandPath("logos") , false, "name" , "marke*.jpg" ) />
<cfset createObject( "java", "java.util.Collections" ).shuffle( Files ) />
<cfloop index="i" from="1" to=#Min(MaxLogos,ArrayLen(Files))# >
<cfset ArrayAppend( Images , Files[i] ) />
</cfloop>
<cfdump var=#Images# />
Upvotes: 3
Reputation: 2178
I'm not sure if your code will actually work as there appears to be several syntactical errors in it. Also you're doing a directory list on img but then pulling images from logos and you've not made it clear what the relationship is between these directories
those issues aside, here is how i would handle this.
<cfscript>
// this code is untested, but should get you going
// get list of image file names as an array
dir = directoryList(expandPath("imgs"), false, "name", "*.jpg");
images = [];
while(true) {
// if out directory list is now empty or we have 5 results, we're done
if(!arrayLen(dir) or arrayLen(images) gte 5) break;
// get an image from a random point in the list
pos = randrange(1, arrayLen(dir));
// append it to our images array
arrayAppend(images, dir[pos]);
// delete form the source array, this avoids duplicates in further iterations
arrayDeleteAt(dir, pos);
}
</cfscript>
This gives you an array of images, with between 0 and 5 elements, which you can then output as a list.
As a side note, its not advisable to use <cfimage> and related functions repeatedly. If you need to resize or manipulate an image you should then cache it back to disk rather than repeating the manipulation every request.
Upvotes: 1