我有一个有序的实体列表。每个实体都有int UniqueKey
属性。
我希望列表经历一个转换,使UniqueKey
值变为唯一(假设存在重复)。这是通过查找重复项并逐步递增它们来完成的。
分步流程:
UniqueId
值,请在当前索引处增加值。例如,{ 1, 1, 1, 3, 3, 8 }
将执行以下步骤:
{ 1, 2, 1, 3, 3, 8 }
:索引1递增{ 1, 2, 2, 3, 3, 8 }
:索引2递增{ 1, 2, 3, 3, 3, 8 }
:索引2再次递增{ 1, 2, 3, 4, 3, 8 }
:索引3递增{ 1, 2, 3, 4, 4, 8 }
:索引4递增{ 1, 2, 3, 4, 5, 8 }
:索引4再次递增下面的代码以非常程序的方式执行上述算法:
entities = entities.OrderBy(x => x.UniqueId);
foreach (var entity in entities)
{
var leftList = entities.Take(entities.IndexOf(entity));
while (leftList.Any(x => x.UniqueId == entity.UniqueId))
{
entity.UniqueId++;
}
}
问题:是否可以在LINQ中实现这一点?
答案 0 :(得分:1)
你的算法可以简化很多。只需迭代,如果Id低于前一个,则将其递增1。没有Linq,没有O(n ^ 2),只有O(n):
{ 1, 2, 1, 3, 3, 8 } : Index 1 incremented
{ 1, 2, 3, 3, 3, 8 } : Index 2 incremented
{ 1, 2, 3, 4, 3, 8 } : Index 3 incremented
{ 1, 2, 3, 4, 5, 8 } : Index 4 incremented
entities = entities.OrderBy(x => x.UniqueId).ToList();
for(int index = 1; index < entities.Count; index++)
{
int previous = entities[index - 1].UniqueId;
if (previous >= entities[index].UniqueId)
{
entities[index].UniqueId = previous + 1;
}
}
答案 1 :(得分:0)
技术上是的:
var indexedEntities =
entities.Select((e, i) => new { Entity = e, Index = i })
.ToList();
indexedEntities.ForEach(ie =>
ie.Entity.UniqueId =
indexedEntities.Any(prev => prev.Index < ie.Index)
&& ie.Entity.UniqueId
<= indexedEntities.TakeWhile(prev => prev.Index < ie.Index)
.Max(prev => prev.Entity.UniqueId)
? indexedEntities.TakeWhile(prev => prev.Index < ie.Index)
.Max(prev => prev.Entity.UniqueId) + 1
: ie.Entity.UniqueId);
var result = indexedEntities.Select(ie => ie.Entity);
虽然请,为了爱IT中所有神圣的东西,不要,只是不要:)
答案 2 :(得分:0)
这并没有忠实地遵循您的算法,但它可能会给您想要的结果。 基本上将每个元素与下一个元素进行比较,并将后者的Id增加为比前者更多。
entities.OrderBy(e => e.Id)
.Aggregate((e1, e2) => { if (e1.Id >= e2.Id) { e2.Id = e1.Id + 1; } return e2; });
答案 3 :(得分:0)
如果你急需一个linq解决方案,为什么不直接使用索引作为id。
entities.OrderBy(x => x.UniqueId).Select((x,i) => {
x.UniqueId = i;
return x;
}).ToArray();