【发布时间】:2015-07-16 14:10:09
【问题描述】:
我正在编写一个方法,它将获取大量文件并将它们拆分为包含相等总磁盘空间的较小列表。例如。一个包含 1 个 100kb 文件的列表,另一个包含 100 个 1kb 文件的列表。
我拥有的代码执行以下操作。如果列表中的所有文件总计超过 500kb,我想将此列表拆分为更小的列表。这意味着如果我的总数为 600kb,我将有 2 个列表。我想在每个列表中添加 300kb(或尽可能接近)的文件。
我编写的代码可以很好地做到这一点,但有一种常见的场景会搞砸。如果我有 99 个文件。 99 个是 1kb,最后一个文件是 400kb。此代码将来回向每个列表添加 1 个文件,直到两个列表都有 49 个文件,每个列表中的每个列表为 49kb,但现在最终文件很大,这意味着 1 个列表将是 49kb,另一个是 449kb。我需要一种聪明的方法来划分文件,以便 400kb 的文件最终出现在一个列表中。
int listcount = (int)Math.Ceiling(totalsize / listlimit); //500kb
List<string>[] lists = new List<string>[listcount];
double[] memorytotals = new double[listcount]; // this array will keep track of what the file size total is in each of the arrays.
foreach(string file in filelist)
{
double size = new FileInfo(file).Length;
int pos = 0;
for (int i = 0; i < memorytotals.Length; i++)
{
if (memorytotals[i] < memorytotals[pos]) { pos = i; }
}
if(size > memorytotals[pos])
{
//get the next smallest array that is not pos
int pos2 = 0;
for (int i = 0; i < memorytotals.Length; i++)
{
if (memorytotals[i] < memorytotals[pos2] && pos2 != pos)
{
pos2 = i;
}
}
//if moving all contents of the smallest array into the second smallest array make for a smaller size than just putting the larger file directly into the smaller array than do it.
double newlistTotal = memorytotals[pos] + memorytotals[pos2];
if(newlistTotal < size)
{
lists[pos2].AddRange(lists[pos]);
//empty the list in order to add the new larger file to this list.
lists[pos].Clear();
}
}
lists[pos].Add(file);
}
【问题讨论】:
-
您可能需要执行一种两遍方案:仅获取文件名和大小的列表,然后从那里分解它们,然后将它们添加到拆分列表中。.
-
这听起来像是packing problem 的变体——你可能想研究通用打包算法
-
也许您可以对所有文件进行排序,其中第一个文件最重。然后运行你的算法,我认为它会起作用。
-
问题不简单,比如400,200,290,47,63,totalSize小于1000,但是如果你的split size是500就必须用3个list来保存
-
嗯,包装问题正是我的问题,非常感谢!我开始怀疑实现均匀大小的列表所需的处理是否会通过处理均匀大小的列表来超过性能提升。我会进一步研究这个问题,看看我是否能想出一种方法来改进我目前的方法,而无需大量额外的处理