2

Given the following strings = new string[] { "a", "a", "a", "b", "b", "c", "c", "c", "c", "d" };

How would you replace the duplicate items to produce the following output: { "a", "Duplicate", "Duplicate", "b", "Duplicate", "c", "Duplicate", "Duplicate", "Duplicate", "d" }

Lau Kondrup
  • 133
  • 13

5 Answers5

7

For something like this, particularly if you intend to modify the array and not produce a new sequence, I would prefer an old fashioned loop. It would seem to me to be more obvious, less "clever," and easier to understand. If you are of a similar opinion, the loop is fairly easy to write. Create a set that will hold distinct items, and replace items that have already been added to the set.

var set = new HashSet<string>();
for (int i = 0; i < strings.Length; i++)
{
    if (set.Contains(strings[i]))
    {
        strings[i] = "Duplicate";
    }
    else
    {
        set.Add(strings[i]);
    }
}

Given your input, your output would be:

a
Duplicate
Duplicate
b
Duplicate
c
Duplicate
Duplicate
Duplicate
d
Anthony Pegram
  • 123,721
  • 27
  • 225
  • 246
  • Just wanted to write this down. IMHO this should be the right answer. – atlaste Jun 01 '16 at 09:04
  • 4
    Good anti LINQ overuse answer! But to make it even better comparable to the "elegant" LINQ way in the other answer, the loop body can be reduced to `if (!set.Add(strings[i])) strings[i] = "Duplicate";` – Ivan Stoev Jun 01 '16 at 09:56
  • Bit off-topic: What are the pros and cons of using HashSet instead of eg. Array or List in this example? – Lau Kondrup Jun 01 '16 at 10:31
  • 1
    @Jenyoin http://stackoverflow.com/questions/6391738/what-is-the-difference-between-hashsett-and-listt – Abbas Jun 01 '16 at 11:27
4

Using Linq, you could do this.

s = s.GroupBy(x=>x)
     .SelectMany(x=>x.Take(1)                                    // Take first element
                     .Concat(x.Skip(1).Select(r=>"Duplicate"))   // Replace other elements with 'Duplicate' 
                )
    .ToArray(); 

Check Working example

Hari Prasad
  • 16,716
  • 4
  • 21
  • 35
  • Very elegant way of doing it. – nik0lai Jun 01 '16 at 09:06
  • 3
    @nik0lias, may be elegant(I personally don't find this code elegant. Take this code and show somebody and ask him what does it do without debugging), but I suspect this will be inefficient comparing to straightforward methods. – Giorgi Nakeuri Jun 01 '16 at 09:08
  • 1
    @nik0lias Elegant? I make it a habit of asking c# candidates in their interviews about what these fancy Linq statements actually _do_. Let's just say that from the many hundreds of candidates that I've talked with, I have yet to interview the first person that actually _knows_ what statements like this one do under the hood. IMHO that's pretty much the definition of a 'bad practice'. – atlaste Jun 01 '16 at 17:01
  • 1
    I'd question those who didn't have an idea of what the above statement is doing. I wouldn't implement that unless I had an idea of the queries behind it. I don't just blindly type LINQ queries nor do I expect others to. If you understand it then it's elegant (IMO). – nik0lai Jun 02 '16 at 07:54
2

In case you are searching for a method which will mark only consecutive duplicates:

var strings = new string[] { "a", "a", "a", "b", "b", "c", "c", "c", "c", "d" };
var output = new string[strings.Length];
output[0] = strings[0];

for(int i = 1; i < strings.Length; i++)
{
    output[i] = strings[i] != strings[i - 1] ? strings[i] : "duplicate";
}
Giorgi Nakeuri
  • 35,155
  • 8
  • 47
  • 75
0

Try This

strings = new string[] { "a", "a", "a", "b", "b", "c", "c", "c", "c", "d" };
var myArray = new System.Collections.ArrayList();

foreach(var item in strings){
    if (!myArray.Contains(item))
        myArray.Add(item);
    else
        myArray.Add('Duplicate');
}
Abbas
  • 14,186
  • 6
  • 41
  • 72
  • A couple of things: `ArrayList` is not a preferred collection to use in modern C#, there are better choices. Secondly, this solution will become increasingly slow as the size of `strings` grows, it will not scale well. – Anthony Pegram Jun 01 '16 at 09:09
0

Just a thought on writing a lambda expression for this

var output = strings.ToList().Select((x, y) => Array.IndexOf(strings, x) == y ? x : "Duplicate");
Manish Rawat
  • 1,142
  • 1
  • 18
  • 34