0

エンティティの順序付きリストがあります。各エンティティにはint UniqueKeyプロパティがあります。

リストを変換して、UniqueKey値を一意にする必要があります (重複があると仮定します)。これは、重複を見つけて徐々に増やしていくことによって行われます。

段階的なプロセス:

  1. インデックス 1 から開始します(ゼロベースのインデックスを使用しています)
  2. 以前の要素に同じUniqueId値がある場合は、現在のインデックスで値を増やします。
  3. 前の要素が同じ UniqueId を持たなくなるまで (2) を繰り返します
  4. 要素を 1 つ右に移動

たとえば{ 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 が前の ID よりも小さい場合は、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;
    }
}
于 2013-11-14T14:57:57.330 に答える
0

This doesn't follow your algorithm faithfully, but it might give you the result you want. Essentially compare each element with the next, and increment the latter's Id to be one more than the former's.

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 に答える