Потенциальная проблема с отслеживанием «используемых» элементов состоит в том, что может быть намного больше итераций, чем необходимо для вывода всех элементов. Например, предположим, что элемент 10 был первым отображаемым элементом, отслеживая его по мере использования, возможно, что 10 снова появится в randrange (), прежде чем все элементы будут отображены. Чем больше элементов «используется», тем выше вероятность того, что нам потребуется добавить итерацию, чтобы получить элемент, который не использовался.
Один из способов убедиться, что мы делаем только 6000 итераций, - это уменьшить размер массива при каждой итерации и выполнить randRange (1, arrayLen ({имя массива})).
//set up array
test = [];
for( x=1; x<=6000; x++ ){
arrayAppend( test, "Item " & x );
}
//here is the meat of the process
done = false;
count = 1;
while( !done ){
index = randRange( 1, arrayLen( test ) );
writeOutput( count & " : " & test[ index ] & "<br/>" );
arrayDeleteAt( test, index );
count++;
done = !arrayLen( test );
}
Приведенный выше код в среднем выполнялся на моей машине разработки менее 100 мс.
Кроме того, после тестирования кода Генри я заметил, что его можно немного подправить, вот слегка оптимизированный код.
<!--- set up the array --->
<cfset theString = []>
<cfloop from="1" to="6000" index="i">
<cfset arrayAppend(theString, "Item : " & i) />
</cfloop>
<cfset collections = createObject("java","java.util.Collections") />
<cfset collections.shuffle( theString ) />
<cfoutput>
<cfloop array="#theString#" index="x">
#x#<br/>
</cfloop>
</cfoutput>
Обратите внимание, что я избавился от arrayresize (), и вы можете просто передать исходный массив в collection.shuffle () и затем выполнить цикл по нему.