2

I have an array which has some duplicate values.
I have to count the number of each duplicate items and their index.
Print such as:

Index of b: 1
Index of b: 4
Index of c: 2
Index of c: 3
Index of c: 5
Index of e: 7
Index of e: 8

Total duplicate b: 2
Total duplicate c: 3
Total duplicate e: 2

    

In my code I'm able to find only duplicate values.

Dim list As New List(Of String) From {"a", "b", "c", "c", "b", "c", "d", "e", "e"}
Dim duplicates = list.GroupBy(Function(x) x).Where(Function(x) x.Count > 1).Select(Function(x) x.Key)

For Each i As String In list.ToArray
    If duplicates.Contains(i) Then
        Debug.WriteLine("Duplicate Element: " & i & "Index:  " & list.IndexOf(i))
    End If
Next

Which gives output:

Duplicate Element: bIndex:  1
Duplicate Element: cIndex:  2
Duplicate Element: cIndex:  2
Duplicate Element: bIndex:  1
Duplicate Element: cIndex:  2
Duplicate Element: eIndex:  7
Duplicate Element: eIndex:  7
0

2 Answers 2

2

You already have an answer, but I propose a slightly different method anyway, it might come in handy after. This uses the same LINQ methods you already have.

The LINQ's query creates an object that contains the value and position of all strings in the elements List, groups the values then selects the groups that contain more than one item and finally orders the groups by their Key value.

Dim elements = {"a", "b", "c", "c", "b", "c", "d", "e", "e"}.ToList()
Dim duplicates = elements.Select(Function(elm, i) New With {.Value = elm, .Index = i}).
                          GroupBy(Function(obj) obj.Value).
                          Where(Function(grp) grp.Count() > 1).
                          OrderBy(Function(grp) grp.Key)

For Each group In duplicates
    For Each dupe In group
        Console.WriteLine($"Duplicate: {dupe.Value} Index = {dupe.Index}")
    Next
    Console.WriteLine($"Number of {group.Key} duplicates: {group.Count()}")
Next

This prints:

Duplicate: b Index = 1
Duplicate: b Index = 4
Number of b duplicates: 2

Duplicate: c Index = 2
Duplicate: c Index = 3
Duplicate: c Index = 5
Number of c duplicates: 3

Duplicate: e Index = 7
Duplicate: e Index = 8
Number of e duplicates: 2
Sign up to request clarification or add additional context in comments.

3 Comments

I was going to contribute too, then I realized my code did not differ from this answer at all. Ha!
@djv There's a possible interesting alternative: since the source is a List<string>, you could use BinarySearch in a loop, using the result as the base index to search the next value. It would be much more efficient and even shorter.
What do you think this is, a job interview? :)
1

An approach

    Dim list As New List(Of String) From {"a", "e", "e", "b", "c", "c", "b", "c", "d", "e"}
    Dim duplicates As IEnumerable(Of String) = list.Distinct
    duplicates = From s In duplicates
                  Where list.FindAll(Function(l) l = s).Count > 1
                  Select s

    For Each s As String In duplicates
        Dim ct As Integer = (From l In list Where l = s Select l).Count
        Debug.WriteLine(s)
        Debug.WriteLine("count:{0}", ct)
        Dim idx As IEnumerable(Of Integer)
        idx = From n In Enumerable.Range(0, list.Count)
              Where list(n) = s
              Select n Take ct

        Debug.WriteLine("Indexes")
        For Each n As Integer In idx
            Debug.Write(n.ToString)
            Debug.Write(" ")
        Next
        Debug.WriteLine("")
    Next

Output

e
count:3
Indexes
1 2 9 
b
count:2
Indexes
3 6 
c
count:3
Indexes
4 5 7 

1 Comment

That's perfect! Thank You.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.