bitshift
bitshift

Reputation: 6852

Approach for reordering a sequence starting in the middle where there are duplicates

Have a list of simple objects that have "TruckNumber" property. Most of the time they are in ascending order eg. 1, 2, 3,4, 8, 11

The problem is sometimes, the system that im getting the data from identifies more than one object with the same TruckNumber. eg. 1, 2, 3, 3, 3, 4, 5, 6, 7, 8, 9

I need a way to transform that list into this
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11

Its unknown, but I think I also need to handle the condition where there are multiple "sets" of duplicate TruckNumber values. eg. 1, 2, 3, 3, 3, 4, 5, 6, 7, 7, 7, 8, 9
which would become 1,2,4,5,6, 7, 8, 9, 10, 11, 12, 13

However, in the examples above, the objects with the TruckNumbers 1, 2 need to remain in that order, as does 8,9

Upvotes: 0

Views: 46

Answers (3)

JohnyL
JohnyL

Reputation: 7152

You could use overload of Select, which accepts index of element:

class Truck { public int TruckNumber { get; set; } }

static void Main(string[] args)
{
    Truck[] trucks =
    {
        new Truck { TruckNumber = 1 }, new Truck { TruckNumber = 2 },
        new Truck { TruckNumber = 3 }, new Truck { TruckNumber = 3 }, new Truck { TruckNumber = 3 },
        new Truck { TruckNumber = 4 }, new Truck { TruckNumber = 5 }, new Truck { TruckNumber = 6 },
        new Truck { TruckNumber = 7 }, new Truck { TruckNumber = 8 }, new Truck { TruckNumber = 9 }
    };                                                                            
    var trucks2 = trucks.Select((tn, index) => { tn.TruckNumber = index + 1; return tn; });
}

Upvotes: 0

JamesFaix
JamesFaix

Reputation: 8665

I think this will do what you want, although it is not very efficient. Using a SortedDictionary may be more optimized.

var startingList = new []
{
   new Thing { TruckNumber = 1 },   
   new Thing { TruckNumber = 2 },
   new Thing { TruckNumber = 2 },
   new Thing { TruckNumber = 3 },
   new Thing { TruckNumber = 4 },
   new Thing { TruckNumber = 5 },
   new Thing { TruckNumber = 5 },
   new Thing { TruckNumber = 6 },
   new Thing { TruckNumber = 7 }
}

var cleanedList = new List<Thing>();

var duplicates = new List<Thing>();

foreach (var thing in startingList) 
{
    if (cleanedList.Any(t => t.TruckNumber == thing.TruckNumber)) 
    {
        duplicates.Add(thing);
    }
    else 
    {
        cleanedList.Add(thing);
    }
}

var lastTruckNumber = cleanedList.Select(t => t.TruckNumber).Max();

foreach (var thing in duplicates) 
{
    var nextTruckNumber = lastTruckNumber + 1;
    thing.TruckNumber = nextTruckNumber;
    lastTruckNumber = nextTruckNumber;
}

return cleanedList;

Upvotes: 0

Johnathan Barclay
Johnathan Barclay

Reputation: 20373

If I understand correctly, you could do this:

static IEnumerable<int> WithoutDuplicates(this IEnumerable<int> source)
{
    int sourceCount = source.Count();
    var distinct = source.OrderBy(i => i).Distinct();
    int distinctCount = distinct.Count();

    if (distinctCount == count)
    {
        return distinct;
    }

    // If items have been removed, append replacements
    int next = distinct.Max() + 1;
    int difference = sourceCount - distinctCount;
    return distinct.Union(Enumerable.Range(next, difference));
}

Then:

var source = new [] { 1, 2, 3, 3, 3, 4, 5, 6, 7, 7, 7, 8, 9 };
source.WithoutDuplicates(); // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13

Upvotes: 1

Related Questions