0

我有一个有序的实体列表。每个实体都有一个int UniqueKey属性。

我希望列表经过转换,从而使UniqueKey值变得唯一(假设有重复项)。这是通过查找重复项并逐步增加它们来完成的。

分步过程:

  1. 从索引 1 开始(我使用从零开始的索引)
  2. 如果任何先前的元素具有相同UniqueId的值,则在当前索引处增加值。
  3. 重复 (2) 直到没有之前的元素具有相同的 UniqueId
  4. 向右移动一个元素

例如,{ 1, 1, 1, 3, 3, 8 }将执行以下步骤:

  1. { 1, 2, 1, 3, 3, 8 }: 索引 1 递增
  2. { 1, 2, 2, 3, 3, 8 }: 索引 2 递增
  3. { 1, 2, 3, 3, 3, 8 }: 索引 2 再次递增
  4. { 1, 2, 3, 4, 3, 8 }: 索引 3 递增
  5. { 1, 2, 3, 4, 4, 8 }: 索引 4 递增
  6. { 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 中实现这一点?

4

4 回答 4

1

你的算法可以简化很多。只需迭代一遍,如果一个 Id 低于前一个,则将其加一。没有 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;
    }
}
于 2013-11-14T14:57:57.330 回答
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 中所有神圣事物的热爱,不要,只是不要 :)

于 2013-11-14T14:54:11.093 回答
0

这不会忠实地遵循您的算法,但它可能会给您想要的结果。基本上将每个元素与下一个元素进行比较,并将后者的 Id 增加为比前者多一个。

entities.OrderBy(e => e.Id)
    .Aggregate((e1, e2) => { if (e1.Id >= e2.Id) { e2.Id = e1.Id + 1; } return e2; });
于 2013-11-14T14:56:56.297 回答
0

如果您迫切需要 linq 解决方案,为什么不直接使用索引作为 id。

entities.OrderBy(x => x.UniqueId).Select((x,i) => {
                                                     x.UniqueId = i;
                                                     return x;
                                                  }).ToArray();           
于 2013-11-14T15:10:57.393 回答