【发布时间】:2017-09-28 13:48:38
【问题描述】:
My.Computer.FileSystem.GetFiles 返回“返回表示目录中文件名的字符串的只读集合。”
我想在集合中随机选择一个文件,处理它,从列表中删除它,然后重复直到处理完所有文件。
我只能想到将集合从 GetFiles 复制到可变集合。 但 GetFiles 最终可能会返回数百万个文件名。
【问题讨论】:
My.Computer.FileSystem.GetFiles 返回“返回表示目录中文件名的字符串的只读集合。”
我想在集合中随机选择一个文件,处理它,从列表中删除它,然后重复直到处理完所有文件。
我只能想到将集合从 GetFiles 复制到可变集合。 但 GetFiles 最终可能会返回数百万个文件名。
【问题讨论】:
只需在函数调用的末尾添加一个.ToList()。
我还建议对列表进行洗牌并迭代洗牌的项目,而不是从列表中间随机选择您的项目。这比从集合中删除项目更容易。
【讨论】:
List<T> 不是链接列表。每次从列表中删除一个项目(调用List.Remove() 或List.RemoveAt(),.Net 分配一个正确大小的新缓冲区并将所有元素复制到新缓冲区。对于洗牌,是的,你需要编写你自己的 shuffle —— 框架应该已经包含了这个开箱即用的内容:(——但是只需谷歌搜索 Fisher-Yates ,你就会发现很多示例代码展示了如何做到这一点而不会大惊小怪。
使用这个泛型函数根据Fisher-Yates Shuffle进行洗牌
Shared r = New Random() ' must not create new Random each time
Public Shared Function Shuffle(Of T)(source As IEnumerable(Of T)) As IEnumerable(Of T)
Dim n = source.Count()
Dim a(n - 1) As T
For i = 0 To n - 1
Dim j = r.Next(0, i + 1)
If i <> j Then
a(i) = a(j)
End If
a(j) = source(i)
Next
Return a
End Function
然后您可以遍历已洗牌的列表。迭代时无需删除项目。
Dim source = My.Computer.FileSystem.GetFiles("C:/")
Dim result = Shuffle(source)
For Each r In result
' process file
Next
【讨论】:
my_mutable_list = My.Computer.FileSystem.GetFiles(my_dir_path).ToList()
然后,根据需要从 my_mutable_list 中删除每个文件。
【讨论】: