C# 将文件分组为500MB块
我有一个C# 将文件分组为500MB块,c#,linq,system.io.fileinfo,C#,Linq,System.io.fileinfo,我有一个文件列表 List<FileInfo> files = GetFiles(); 这里有一些有效的方法 List<FileInfo> files = new List<FileInfo>(); List<List<FileInfo>> listOfLists= new List<List<FileInfo>>(); files.ForEach(x => { var match = list
文件列表
List<FileInfo> files = GetFiles();
这里有一些有效的方法
List<FileInfo> files = new List<FileInfo>();
List<List<FileInfo>> listOfLists= new List<List<FileInfo>>();
files.ForEach(x => {
var match = listOfLists.FirstOrDefault(lf => lf.Sum(f => f.Length) + x.Length < 500*1024*1024);
if (match != null)
match.Add(x);
else
listOfLists.Add(new List<FileInfo>() { x });
});
List files=newlist();
List listOfLists=新列表();
files.ForEach(x=>{
var match=listOfLists.FirstOrDefault(lf=>lf.Sum(f=>f.Length)+x.Length<500*1024*1024);
如果(匹配!=null)
匹配。添加(x);
其他的
Add(newlist(){x});
});
以下是一些有效的方法
List<FileInfo> files = new List<FileInfo>();
List<List<FileInfo>> listOfLists= new List<List<FileInfo>>();
files.ForEach(x => {
var match = listOfLists.FirstOrDefault(lf => lf.Sum(f => f.Length) + x.Length < 500*1024*1024);
if (match != null)
match.Add(x);
else
listOfLists.Add(new List<FileInfo>() { x });
});
List files=newlist();
List listOfLists=新列表();
files.ForEach(x=>{
var match=listOfLists.FirstOrDefault(lf=>lf.Sum(f=>f.Length)+x.Length<500*1024*1024);
如果(匹配!=null)
匹配。添加(x);
其他的
Add(newlist(){x});
});
这里有一个通用的BatchBySize
扩展方法,您可以使用:
public static IEnumerable<List<TSource>> BatchBySize<TSource>(
this IEnumerable<TSource> source,
Func<TSource, long> sizeSelector,
long maxSize)
{
var list = new List<TSource>();
long sumSize = 0;
foreach (var item in source)
{
var itemSize = sizeSelector(item);
if (sumSize + itemSize > maxSize && list.Count > 0)
{
yield return list;
list = new List<TSource>();
sumSize = 0;
}
list.Add(item);
sumSize += itemSize;
}
if (list.Count > 0) yield return list;
}
公共静态IEnumerable BatchBySize(
这是一个数不清的来源,
函数大小选择器,
长(最大尺寸)
{
var list=新列表();
长sumSize=0;
foreach(源中的var项)
{
var itemSize=大小选择器(项目);
if(sumSize+itemSize>maxSize&&list.Count>0)
{
收益回报表;
列表=新列表();
sumSize=0;
}
列表。添加(项目);
sumSize+=项目大小;
}
如果(list.Count>0)收益返回列表;
}
用法示例:
List<List<FileInfo>> result = files
.BatchBySize(x => x.Length, 500_000_000)
.ToList();
列表结果=文件
.BatchBySize(x=>x.长度,500_000_000)
.ToList();
这里有一个通用的BatchBySize
扩展方法,您可以使用:
public static IEnumerable<List<TSource>> BatchBySize<TSource>(
this IEnumerable<TSource> source,
Func<TSource, long> sizeSelector,
long maxSize)
{
var list = new List<TSource>();
long sumSize = 0;
foreach (var item in source)
{
var itemSize = sizeSelector(item);
if (sumSize + itemSize > maxSize && list.Count > 0)
{
yield return list;
list = new List<TSource>();
sumSize = 0;
}
list.Add(item);
sumSize += itemSize;
}
if (list.Count > 0) yield return list;
}
公共静态IEnumerable BatchBySize(
这是一个数不清的来源,
函数大小选择器,
长(最大尺寸)
{
var list=新列表();
长sumSize=0;
foreach(源中的var项)
{
var itemSize=大小选择器(项目);
if(sumSize+itemSize>maxSize&&list.Count>0)
{
收益回报表;
列表=新列表();
sumSize=0;
}
列表。添加(项目);
sumSize+=项目大小;
}
如果(list.Count>0)收益返回列表;
}
用法示例:
List<List<FileInfo>> result = files
.BatchBySize(x => x.Length, 500_000_000)
.ToList();
列表结果=文件
.BatchBySize(x=>x.长度,500_000_000)
.ToList();
使用linq或group by无法实现这一点。您可以做的是设置最小值和最大值,并在进入最小值和最大值范围(例如,450到500 mb)时添加到子列表中。在下一次迭代中,将子列表添加到列表的主列表中,然后转到下一个子列表。如果您需要示例代码,请告诉我。我建议您首先提出一个适合您的非linq解决方案,然后看看它是否可以“linqified”。分而治之。而且,Linq只是一个工具。如果它不起作用,请使用起作用的工具。一些问题:您希望块大小均匀分布吗?或者你能忍受,比如说1-500MB 2-480MB3-450MB 4-470MB 5-100MB吗?@Fildor块应该尽可能多的文件-只要低于500MB。因为这对算法很重要。在接近500MB或更低的阈值时,您可以付出很大的努力。更少可能会使算法更简单,速度更快,但可能会导致更大的大小抖动。更多的努力可能会更慢、更复杂,但会给你最大化的块。也许两种方法都值得一试,让他们互相竞争,看看哪一种最合适。你不能用linq或group by来实现这一点。您可以做的是设置最小值和最大值,并在进入最小值和最大值范围(例如,450到500 mb)时添加到子列表中。在下一次迭代中,将子列表添加到列表的主列表中,然后转到下一个子列表。如果您需要示例代码,请告诉我。我建议您首先提出一个适合您的非linq解决方案,然后看看它是否可以“linqified”。分而治之。而且,Linq只是一个工具。如果它不起作用,请使用起作用的工具。一些问题:您希望块大小均匀分布吗?或者你能忍受,比如说1-500MB 2-480MB3-450MB 4-470MB 5-100MB吗?@Fildor块应该尽可能多的文件-只要低于500MB。因为这对算法很重要。在接近500MB或更低的阈值时,您可以付出很大的努力。更少可能会使算法更简单,速度更快,但可能会导致更大的大小抖动。更多的努力可能会更慢、更复杂,但会给你最大化的块。也许两种方法都值得一试,让它们互相对比,看看哪一种最适合。Info@OP:这是“减少最大块大小的工作量”的一个例子。Info@OP:这是“减少最大块大小的工作量”的一个例子。