有一种简单的方法可以在AppleScript中混洗列表吗?
我做了几次搜索并画了一个空白。
答案 0 :(得分:2)
Fisher-Yates算法的较短版本:
on shuffle(l)
set i to count of l
repeat while i ≥ 2
set j to random number from 1 to i
tell l to set {item i, item j} to {item j, item i}
set i to i - 1
end repeat
l
end shuffle
set l to {}
repeat 1000 times
set end of l to random number from 1 to 1000
end repeat
shuffle(l)
有i * ... * 2 =我!可能的随机数序列。所有这些都恰好对应于i中的一个排列!列表的排列。
使用脚本对象的更快版本:
on shuffle(input)
script s
property l : input
end script
set i to count of l of s
repeat while i ≥ 2
set j to random number from 1 to i
set {item i of l of s, item j of l of s} to {item j of l of s, item i of l of s}
set i to i - 1
end repeat
l of s
end shuffle
脚本采用了:
所以第一个脚本具有指数时间复杂度。 regulus发布的脚本略慢。
当我将第一个脚本保存为scpt并将10000个元素添加到列表中时,我遇到了limit for the number of items that can be saved in a compiled script。
答案 1 :(得分:1)
我想我已经破解了它。包含在易于使用的功能中。
set myList to {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
set answer to listShuffle(myList)
on listShuffle(theList)
set listLength to count of theList
repeat while listLength > 1
set r to random number from 1 to listLength
set item1 to item listLength of theList
set item2 to item r of theList
set item listLength of theList to item2
set item r of theList to item1
set listLength to listLength - 1
end repeat
return theList
end listShuffle
答案 2 :(得分:1)
这是另一种选择。我们只是从列表中随机抓取项目并将它们插入新列表,而不是“洗牌”列表......
set myList to {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
set randomizedList to randomizeList(myList)
on randomizeList(theList)
set listCount to count of theList
set newList to {}
repeat listCount times
set subListCount to count of theList
set r to random number from 1 to subListCount
set end of newList to item r of theList
-- remove the random item from theList
if subListCount is 1 then
exit repeat
else if r = 1 then --> first item
set theList to items 2 thru end of theList
else if r = subListCount then --> last item
set theList to items 1 thru -2 of theList
else
set theList to items 1 thru (r - 1) of theList & items (r + 1) thru -1 of theList
end if
end repeat
return newList
end randomizeList
编辑 :如果您想加快大型列表上的操作,可以使用脚本对象。当列表很大时,您经常会看到很大的速度增益。所以你可以用脚本对象这样写代码......
set myList to {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
set answer to listShuffle(myList)
on listShuffle(theList)
script s
property l : missing value
end script
set s's l to theList
set listLength to count of s's l
repeat while listLength > 1
set r to random number from 1 to listLength
set item1 to item listLength of s's l
set item2 to item r of s's l
set item listLength of s's l to item2
set item r of s's l to item1
set listLength to listLength - 1
end repeat
return s's l
end listShuffle
答案 3 :(得分:0)
如果新列表中的项目不必是唯一的,那么您可以使用非常高效的
set selectedItemVar to some item of list someItemListVar
答案 4 :(得分:0)
我会抛弃我的解决方案。我个人只使用非常短的列表(大约200个项目),我需要从中提取各种长度的独特,随机的子列表。将该算法完整地应用于列表(即,为count of mainList
传递maxCount
)将导致原始列表的混洗版本。这不是为速度而构建的,但对于那些算法不强的人来说可能更容易获得。
on randomizedSublist(mainList, maxCount)
set sublist to {} as list
repeat with x from 1 to maxCount
set oneItem to some item of mainList
repeat until sublist does not contain oneItem
set oneItem to some item of mainList
end repeat
set end of sublist to oneItem
end repeat
return sublist
end randomizedSublist