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.
You could use Dictionary.lookup to do this more cleanly as well:
Dict.value(a) = Dict.Lookup(a,0) + 1
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
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)
If Not NumbersList.HasKey(RandomNumber) Then
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
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
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
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
then your code:
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
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.)
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.
@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.
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.