我有一个系统将大量未排序的对象列表中的数据插入存储系统。存储系统根据对象的TypeKey为插入分配处理(注意 - 存在提供唯一性的辅助键)。有多个具有相同TypeKey的对象,但这不会在对象列表中平均分配。如果我按顺序插入太多相同的键,则进程可能会受到限制,因此不执行此操作会有很大的优势。
我的目标是获取未排序的对象列表,并按照最大化(或最佳尝试)具有相同TypeKey的对象之间距离的顺序将它们添加到线程安全队列中。
注意 - 我在.NET Framework 4.6上的C#中这样做。如果我可以避免它,我想避免许多外部依赖。
示例:
class DataPack
{
public string TypeKey {get; set;}
public string UniqueKey {get; set;}
public object DataPackage {get; set;}
}
伪代码
List<DataPack> rawList = {lotsa data, ~80k datapacks spread across 3000+ keys}
List<DataPack> maxDistSortedList = rawList.OrderByMaxDist(); //Not real function
ConcurrentQueue<DataPack> cq = new ConcurrentQueue<DataPack>();
ForEach (DataPack item in maxDistSortedList)
{
cq.Enqueue(item);
}
然后,我将从并行进程内的ConcurrentQueue中提取数据,以将数据发送到存储系统。
此时我正在集思广益创建排序算法的想法,但我似乎正在为一个高效的过程打一堵墙,不需要通过多个循环进行大量的迭代。
答案 0 :(得分:1)
我可能错过了一些东西,但想法是先用Typekey对它们进行分组,然后使用带有两个参数的select方法为typekey组中的每个条目分配一个索引,然后按该索引排序。然后它将获取TypeKey-1的第一个条目,TypeKey-2的第一个条目,TyperKey-n的第一个条目,然后重新开始使用TypeKey-1的第二个,等等。
var newList=rawList
.GroupBy(x=>x.TypeKey)
.Select(x=>x.Select((y,i)=>new {y=y,i=i}))
.SelectMany(x=>x)
.OrderBy(x=>x.i)
.Select(x=>x.y);
测试代码:
void Main()
{
var massdata=new List<DataPack>(){
new DataPack {TypeKey="0001",UniqueKey="0000",DataPackage="yes"},
new DataPack {TypeKey="0001",UniqueKey="0001",DataPackage="yes"},
new DataPack {TypeKey="0001",UniqueKey="0002",DataPackage="yes"},
new DataPack {TypeKey="0001",UniqueKey="0003",DataPackage="yes"},
new DataPack {TypeKey="0001",UniqueKey="0004",DataPackage="yes"},
new DataPack {TypeKey="0001",UniqueKey="0005",DataPackage="yes"},
new DataPack {TypeKey="0001",UniqueKey="0006",DataPackage="yes"},
new DataPack {TypeKey="0001",UniqueKey="0007",DataPackage="yes"},
new DataPack {TypeKey="0001",UniqueKey="0008",DataPackage="yes"},
new DataPack {TypeKey="0001",UniqueKey="0009",DataPackage="yes"},
new DataPack {TypeKey="0002",UniqueKey="0010",DataPackage="yes"},
new DataPack {TypeKey="0002",UniqueKey="0011",DataPackage="yes"},
new DataPack {TypeKey="0002",UniqueKey="0012",DataPackage="yes"},
new DataPack {TypeKey="0002",UniqueKey="0013",DataPackage="yes"},
new DataPack {TypeKey="0002",UniqueKey="0014",DataPackage="yes"},
new DataPack {TypeKey="0002",UniqueKey="0015",DataPackage="yes"},
new DataPack {TypeKey="0002",UniqueKey="0016",DataPackage="yes"},
new DataPack {TypeKey="0002",UniqueKey="0017",DataPackage="yes"},
new DataPack {TypeKey="0002",UniqueKey="0018",DataPackage="yes"},
new DataPack {TypeKey="0002",UniqueKey="0019",DataPackage="yes"},
new DataPack {TypeKey="0003",UniqueKey="0020",DataPackage="yes"},
new DataPack {TypeKey="0003",UniqueKey="0021",DataPackage="yes"},
new DataPack {TypeKey="0003",UniqueKey="0022",DataPackage="yes"},
new DataPack {TypeKey="0003",UniqueKey="0023",DataPackage="yes"},
new DataPack {TypeKey="0003",UniqueKey="0024",DataPackage="yes"},
new DataPack {TypeKey="0003",UniqueKey="0025",DataPackage="yes"},
new DataPack {TypeKey="0003",UniqueKey="0026",DataPackage="yes"},
new DataPack {TypeKey="0003",UniqueKey="0027",DataPackage="yes"},
new DataPack {TypeKey="0003",UniqueKey="0028",DataPackage="yes"},
new DataPack {TypeKey="0003",UniqueKey="0029",DataPackage="yes"},
};
var result=massdata
.GroupBy(x=>x.TypeKey)
.Select(x=>x.Select((y,i)=>new {y=y,i=i}))
.SelectMany(x=>x)
.OrderBy(x=>x.i)
.Select(x=>x.y);
result.Dump();
}
// Define other methods and classes here
class DataPack
{
public string TypeKey {get; set;}
public string UniqueKey {get; set;}
public object DataPackage {get; set;}
}
结果:
现在,如果有一个类型键的条目多于其他类型键,那么最后会出现问题,因为它们都是那个类型键,但这是一个快速的解决方案,不一定是最好的解决方案。