# Matching duplicate values in an array

I was wondering if there’s a way to determine which values are duplicated in an array?

There are many. All are brute force. It depends on the desired result. Do you want a list of dupes? A list of non dupes? Or an array that contains all but one of the dup values removed, so there are no more dupes?

Hi Tim! So I’m not looking to remove the duplicate values but rather get the app to list the values that are duplicated and how many duplications there are for each value.

So what I have is a listbox that contains a number in each row. I created an array that contains this list of numbers. Now I want to know which numbers are repeating and how many times.

I’d use a dictionary. Check if the value exists already in the dictionary. If not, add your value as the Key and 1 for the dictionary Value. If it does, add 1 to the dictionary value. Then loop through the dictionary and pull all the keys that have a value greater than 1. The dictionary value is the number of times the key repeated.

5 Likes

You could use Dictionary.lookup to do this more cleanly as well:

`Dict.value(a) = Dict.Lookup(a,0) + 1`

5 Likes

Thanks Tim & Greg. I will definitely give this a try.

Hello,
103 / 5.000

## Übersetzungsergebnisse

Hello Markus
if only one display is desired, the values can be counted by sorting see example

https://www.dropbox.com/s/g6m73glxnljwybg/%20Listbox-dublicated%20entries-API2.xojo_binary_project?dl=1

1 Like

A quick & dirty example of the approach @Tim_Hare suggested:

``````Var NumbersList As New Dictionary
Var RandomNumber As Integer

For X As Integer = 0 To 100

RandomNumber = System.Random.LessThan(25)

NumbersList.Value(RandomNumber) = 1

Else

NumbersList.Value(RandomNumber) = NumbersList.Value(RandomNumber)+1

End If

Next

Var DoublesMessage As String

For Each key As Variant In NumbersList.Keys

If NumbersList.Value(key) > 1 Then

DoublesMessage = DoublesMessage + "The Number " + key.StringValue + " is contained " + Str(NumbersList.Value(key)) + " times." + EndOfLine

End If

Next

MessageBox DoublesMessage
``````
1 Like

And @Greg_O suggestion in comparison:

``````Var NumbersList As New Dictionary
Var RandomNumber As Integer

For X As Integer = 0 To 100

RandomNumber = System.Random.LessThan(25)

NumbersList.Value(RandomNumber) = NumbersList.Lookup(RandomNumber,0)+1

Next

Var DoublesMessage As String

For Each key As Variant In NumbersList.Keys

If NumbersList.Value(key) > 1 Then

DoublesMessage = DoublesMessage + "The Number " + key.StringValue + " is contained " + Str(NumbersList.Value(key)) + " times." + EndOfLine

End If

Next

MessageBox DoublesMessage
``````

Sorry, but i had a few moments of spare time and needed something to do 1 Like

Thanks Sascha! So the example you gave worked perfectly for the random number. However, when I tried to implement the array I created from the listbox, I’m getting no results.

``````var numberslist as new dictionary

for i as integer = 0 to list.listcount - 1

var str() as string = array(list.cell(i,0))
numberslist.value(i) = numberslist.lookup(str,0)+1

next i

Var DoublesMessage As String

for each key as variant in numberslist.keys

if numberslist.value(key) > 1 Then

DoublesMessage = DoublesMessage + "The Number " + key.StringValue + " is contained " + Str(NumbersList.Value(key)) + " times." + EndOfLine

End If

Next

msgbox doublesmessage
``````

What could I be doing wrong?

I’m also slightly confused on where the count is taking place or how it’s taking place. I’m assuming here

``NumbersList.Value(RandomNumber) = NumbersList.Lookup(RandomNumber,0)+1``

Another possibility is to use an in memory database /recordset

If you populate that with all your records…

1
1
1
3
3
2
4
1
5

Then you can get your list using a simple SQL query

`Select number, count(1) as tot group by tot having tot >1 ;`

From the list above, you would get rows containing
1 , 4 and
3, 2

1 Like

This doesn’t look anything like what @Greg_O posted.

Well I thought that I should modify the values since I’m not looking for a list of random numbers. Unless I’m misunderstanding this line of code…and apparently I am. Which is why I’m here.

If you see the code posted by Sasha:

``````RandomNumber = System.Random.LessThan(25)
NumbersList.Value(RandomNumber) = NumbersList.Lookup(RandomNumber,0)+1
``````

``````  var str() as string = array(list.cell(i,0))
numberslist.value(i) = numberslist.lookup(str,0)+1
``````

I guess what you want is something like:

``````var mynumber as integer = Listbox1.Cell(i,0).ToInteger //or CellTextAt
numberslist.value(mynumber) = numberslist.lookup(mynumber,0)+1
``````
2 Likes

You’re using the row number as the dictionary key. That will always be unique. You should use the value of the listbox as the dictionary key. (And it can be a string, you don’t have to convert it to an integer.)

1 Like

The line of code is intended to increment the value assigned for a particular key in the dictionary, whether or not (and this is the important part of the deal) that key already exists (more exactly, to initialise the value if it does not). If you were to lookup the doc for `.Value` and `.Lookup`, you’d see that you can’t have `.Value` on the RHS because if the key doesn’t exist, then you get an exception. IOW, you can’t do something likre:

``````Dict.Value(a) = Dict.Value(a) + 1
``````

unless you know that this key is already in the dictionary and its `.Value` is zero.

@Greg_O 's neat trick relies on the fact that` .Lookup` doesn’t mind if the key exists or not. If it does not, then `.Lookup` just returns the second argument, zero in this case. Thus for a non-existent key the result is to create the key and set the value to one, the desired outcome.

3 Likes

@Tim_Hare yep that was the issue. I didn’t think about the fact that the value couldn’t be unique.

@TimStreater thanks for explaining. I’ve been using xojo since it was Realbasic 5.5 version and I’m just now starting to actually understand certain functions. It’s like things are much more easier to comprehend. So I will definitely start to research dictionary more. I really appreciate everyone for helping out.

1 Like

not sure how fast (or slow) the dictionary approach is, but what I do is sort the array then run down it looking for identical adjacent values ie if x(j) = x(j+1), if so, you have a duplicate, then index down to the next different value and keep looking for another match @ j & j+1.