Finding the Most Frequent and Least Frequent Values in an Array
Hey i have some code to a program, but i need to find the most frequent and least frequent numbers from an array. (that were chosen from a combo-box and added to an array) How do i go about this? This is my code.
Code:
Public Class frm1
Dim arrAisle(100) As String
Dim intIndex As Integer
Dim intCurrentElement As Integer
Dim intCurrentValue As Integer
Dim intElementFreq As Integer
Dim intLargestFreq As Integer
Dim intLeastFreq As Integer
Dim decTotalCost As Decimal
Dim decAvgCost As Decimal
Private Sub frm1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For i = 1 To 10
cboxAisle.Items.Add(i)
Next
cboxAisle.DropDownStyle = ComboBoxStyle.DropDownList
End Sub
Private Sub btnPurchase_Click(sender As Object, e As EventArgs) Handles btnPurchase.Click
Try
AddtoArray()
intIndex += 1
Catch ex As IndexOutOfRangeException
ReDim Preserve arrAisle(intIndex * 2)
AddtoArray()
intIndex += 1
End Try
End Sub
Private Sub AddtoArray()
If txtCost.Text <> "" Then
arrAisle(intIndex) = txtCost.Text
arrAisle(intIndex) = cboxAisle.SelectedText
decTotalCost = decTotalCost + txtCost.Text
decAvgCost = decAvgCost + txtCost.Text
intLargestFreq = intLargestFreq + cboxAisle.SelectedItem
intLeastFreq = intLeastFreq + cboxAisle.SelectedItem
txtCost.Clear()
txtCost.Focus()
End If
End Sub
Private Sub btnFinalise_Click(sender As Object, e As EventArgs) Handles btnFinalise.Click
Array.Sort(arrAisle)
For i As Integer = 0 To intIndex
intCurrentElement = arrAisle(i)
If intCurrentElement = intCurrentValue Then
intElementFreq += 1
ElseIf i > 0 Then
If intElementFreq > intLargestFreq Then
lblMost.Text = arrAisle(i - 1)
intLargestFreq = intElementFreq
ElseIf intElementFreq < intLeastFreq Then
lblLeast.Text = arrAisle(i - 1)
intLeastFreq = intElementFreq
End If
intCurrentValue = intCurrentElement
intElementFreq = 1
End If
Next
decAvgCost = decAvgCost / intIndex
lblMost.Text = "Most Items - Aisle:" & intLargestFreq
lblLeast.Text = "Least Items - Aisle:" & intLeastFreq
lblTotal.Text = "Total cost per item : " & FormatCurrency(decTotalCost)
lblAverage.Text = "Average cost per item : " & FormatCurrency(decAvgCost)
End Sub
End Class
as you can see, i need the most frequently chosen numbers from the cboxAisle to be shown in lblMost and the least frequently chosen number to be shown in lblLeast.
Thanks :) :)
Re: Finding the Most Frequent and Least Frequent Values in an Array
Oh oops, my mistake.
So does anyone know how to find the Most and Least Frequent Elements in an Array?
BTW The code on my 1st Post is different to the one posted by 'jmcilhinney' in Post 2. So if you wanna manipulate the code use my post.
Thanks!!
Re: Finding the Most Frequent and Least Frequent Values in an Array
As for the problem, you don't just pluck code out of the air without knowing what it's supposed to. When I say "what it's supposed to do" I don't just mean the final result but the individual steps required to achieve that result. The key to solving almost any programming problem is to first forget that it's a programming problem. Pretend that you have to do it manually, with pen and paper. Firstly, determine how you would do it. Secondly, determine how you would explain it to someone else in such simple terms that they couldn't go wrong. That right there is the solution to your problem. Only then does the programming part come, i.e. writing code to implement the solution that you already have. You can do those first two parts for yourself because they don't take any coding experience at all. Once you've got the list of steps, each one will be so elementary that you can have a pretty good go at implementing them for yourself too. When you encounter issues in doing that, THAT is when you should post here, showing us what you've done and explaining exactly how it doesn't achieve your aim, which would include the specific step that the problem code is supposed to implement.
To get you started, what you would probably do is start going through the values you have and update a tally for each one as you encounter it. If the number doesn't exist in your list of tallies then add it and start the tally at 1. If it does exist, increment the tally. When you done, you can use one of a number of ways to determine the largest tally and the value it corresponds to.
Re: Finding the Most Frequent and Least Frequent Values in an Array
how do i start a tally in VB
Re: Finding the Most Frequent and Least Frequent Values in an Array
Quote:
Originally Posted by
dannyb.4
how do i start a tally in VB
So, you're going to ignore the whole first paragraph? You're free to do that if you want but I'm afraid that I won't be helping further if you do. Also, I'm not sure that you've given it much thought, given that you posted one minute after I did. A tally is simply a count and I think you already know how to store numbers that you would count with. In fact, I know you do because you're already doing it in the code you posted.
Re: Finding the Most Frequent and Least Frequent Values in an Array
I would experiment with simply sorting the list - the array - and then just walking through it in a loop and counting the items before each "break" of new data.
Re: Finding the Most Frequent and Least Frequent Values in an Array
The data structure most people use as a tally is a Dictionary(Of TKey, TValue). If you're a student or newbie, you may have never seen it. Some people forget newbies exist.
You know what an array is. Lots of variables of the same type in one place, you access them by index. A Dictionary is a fancier array. It has lots of elements of one type ("the value") but instead of indexing it by a number, you index it by a different type (the "key"). So it really stores two things for each entry: a key and a value. That might give you an idea why it has the type parameters TKey and TValue!
Here's a dictionary that lets me store Integer data that represents a player's high score and index it by a player's username. I'll add a few items to it, then print a few items to demonstrate how it works.
Code:
Dim highScoreLookup As New Dictionary(Of String, Integer)()
' You can add values with "Add", or just using the indexer.
highScoreLookup.Add("Fluttershy", 5000)
highScoreLookup("Rainbow Dash") = 87000
' It is an error to try to add the same key twice! So only
' use Add() if it's important you don't replace an existing
' value.
' highScoreLookup.Add("Fluttershy", 5000) <- Error!
' You can also use ContainsKey() to see if a value exists first:
If highScoreLookup.ContainsKey("Fluttershy") Then
Console.WriteLine("Fluttershy has a high score!")
End If
' You can change a value by using the indexer.
highScoreLookup("Fluttershy") = 5500
' You can retrieve values using the indexer.
Dim fluttershyScore As Integer = highScoreLookup("Fluttershy")
Console.WriteLine("Fluttershy: {0}", fluttershyScore)
' But if a value does not exist, it is an error when you try to
' index!
' Dim sombraScore As Integer = highScoreLookup("Sombra") <- Error!
' If you aren't sure if a value exists, you can use ContainsKey()
' to check, but you can also use TryGetValue().
Dim rainbowDashScore As Integer
If highScoreLookup.TryGetValue("Rainbow Dash", rainbowDashScore) Then
Console.WriteLine("Rainbow Dash: {0}", rainbowDashScore)
End If
The reason a Dictionary is so good for tallies is you can make the key be the things you are counting and the value be a count. Then you can go over the array and add 1 to each item's count as you iterate. When you're done, you'll have a list of all the values and how many times they showed up in unsorted order. So how do you get those? Here's another quick demo program:
Code:
Dim tally As New Dictionary(Of String, Integer)
' I'm adding some fake values, because I haven't explained
' how to do the tally algorithm.
tally("Steven") = 12
tally("Pearl") = 8
' If you use a For Each loop, the type you get back is
' KeyValuePair(Of TKey, TValue). That means it's a type with
' a Key and a Value:
Console.WriteLine("All tally values:")
For Each pair In tally
Console.WriteLine(" {0}: {1}", pair.Key, pair.Value)
Next
' You can also use the Keys and Values properties to get a
' collection of either keys or values. The type of these
' is difficult, it's best to use Option Infer here and just
' know "It's a lot of TKey" or "It's a lot of TValue".
Dim names = tally.Keys
Dim values = tally.Values
For Each value In values
Console.WriteLine(value)
Next
Now you know enough that, if you're a bit gifted, you could go off in a corner and finish it yourself. Some nudges would probably help though.
Keeping a tally of an array involves iterating over the array and adding to a tally for each value. Technically, you could do this as items are being added, but I'm going to do it the more roundabout way. Let's say I have an array of Foo objects, and I want to get a tally. This does the trick, and is a little more complex in VB than it is in some other languages:
Code:
Dim tally As New Dictionary(Of Foo, Integer)
For Each item As Foo in MyArray
If Not tally.ContainsKey(item) Then
tally(item) = 1
Else
tally(item) += 1
End If
Next
It's an error to use += if the item isn't there yet, so we have to check first. In some languages, accessing a key that doesn't exist automatically adds a default value for it. The .NET Dictionary type does not behave this way, so remember this trick!
When that is finished, tally will have a list of key/value pairs that represent the count of each Foo in the array*. To know the most frequent and least frequent, you need to do more work. I'm not going to explain that part, I do agree that you should have to figure out SOME of your assignment. Here's some hints that, with some searches, ought to yield fruit.
- The least frequent value is the KeyValuePair with the smallest Value.
- The most frequent value is the KeyValuePair with the largest Value.
- People ask, "How do I find the largest/smallest value in an array?" all the time, and those answers will be useful.
- szlamany's answer is a powerful hint at one way to do so. Think about where the biggest and smallest items might be in a sorted array.
- Some one-line solutions exist, but may not get you the best grade on your homework depending on your teacher.
You will use this tally algorithm and those algorithms for finding the biggest/smallest thing in a list thousands of times over a programming career. So it's important to understand them and be able to write them from memory. The first few times are very hard. The next ten are a lot easier. By the hundredth, you won't even think about it.
* There is a really good reason why, if Foo is a class, we might end up with a ton of 1 tallies instead of an actual count. Classes don't implement "equals" in a way that makes a lot of sense to beginners. But the primitive types like String, Integer, and Double implement it in a way that makes this work. You have to do a fancier things to count classes, and I already wrote plenty.
Re: Finding the Most Frequent and Least Frequent Values in an Array
Quote:
Originally Posted by
Sitten Spynne
The data structure most people use as a tally is a Dictionary(Of TKey, TValue).
I'm guessing that this is an assignment and, if so, concurrent arrays is probably the expected data structure, based on the original code. That would mean one array for the distinct values and another array for the corresponding tallies. The Array.Sort method will then sort the values based on the tallies, allowing the most and least common values to be picked off the ends of the array. If this is homework then using something like a Dictionary, which will not have been taught a this stage, may not be allowed to be used. Then again, it might. For this specific purpose though, concurrent arrays might even be a better option, given the ease with which they can be sorted and the two extremes found.
Re: Finding the Most Frequent and Least Frequent Values in an Array
i'm not quite sure i understand what is needed, but i think that just using the first step of the counting sort algoritm will do
Code:
Public Class Form1
Dim MyInteger As Integer
Dim Myarray(10) As Integer
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Label1.Top = 10
Label1.Left = 120
Label2.Top = Label1.Top + Label1.Height
Label2.Left = Label1.Left
For i = 1 To 10
cboxAisle.Items.Add(i)
Next
Label1.Text = ""
Label2.Text = ""
For i = 0 To 10
Label1.Text = Label1.Text & i.ToString & " "
Next
End Sub
Private Sub cboxAisle_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboxAisle.SelectedIndexChanged
Dim S As String
MyInteger = Integer.Parse(cboxAisle.Text, MyInteger)
Myarray(MyInteger) = Myarray(MyInteger) + 1
Label2.Text = ""
For i = 0 To 10
S = S & Myarray(i).ToString & " "
Next
Label2.Text = S
End Sub
End Class