Add index to duplicate entry in List I wrote this piece of code to append index to any duplicate entry in List&lt;T&gt; like in the sample below.

Input

["dupe", "not dupe", "dupe", "also not dupe"]


Output

["dupe1", "not dupe", "dupe2", "also not dupe"]


But the problem is it's O(n^2) in the second loop and I'm working on a large list (30+ items). I'm very new to C# and didn't know much built-in functions, so I wanted to know is there anything I can do to optimize this?

List&lt;string&gt; duplicate = new List&lt;string&gt;(); // For storing duplicate item
IEnumerable&lt;IGrouping&lt;string, string&gt;&gt; g = header.GroupBy(i =&gt; i);

// Find duplicate and store it in duplicate
foreach (var item in g)
    if (item.Count() &gt; 1)
        duplicate.Add(item.Key);

// Loop through duplicate to append the index
foreach (var item in duplicate) {
    int start = 1;
    for (int i = 0; i &lt; header.Count; i++) {
        // If header[i] is a duplicate item append index to it.
        if (string.Equals(header[i], item, StringComparison.OrdinalIgnoreCase)) {
            header[i] = string.Format("{0}{1}", header[i], start);
            start++;
        }
    }
}
If you collect the indices along with the duplicates, you don't need to loop over the list again:

var header = new List&lt;string&gt;();
var duplicates = header.Select((x, index) =&gt; new { x, index }).ToLookup(x =&gt; x.x, x =&gt; x.index);
foreach(var duplicate in duplicates.Where(x =&gt; x.Count() &gt; 1)) {
  var start = 1;
  foreach(var index in duplicate) {
    header[index] = $"{duplicate.Key}{start++}";
  }
}


This uses string interpolation ($-strings) as a shorthand for string.Format.



On premature optimisation:

You seem concerned about the \$O(n^2)\$ performance of your solution. At the same time you mention your actual input will have ~30 items. Before spending too much time worrying about the efficiency of your code, did you try to find out whether your current solution is problematic? It seems to me that the list is small enough that even a less efficient solution should be quick enough. 

Before trying to optimise specific parts of your code, ask yourself two things:


Do I need to optimise? Is execution time currently a problem?
Where is the efficiency problem in the code?


Before optimising, profile your program to figure out where the problems actually are. Before that, efficiencies like  \$O(n^2)\$  or \$O(n \log n)\$ are purely academic.