Solved

parse string of IDs for count, then list name & count

Posted on 2011-09-20
5
189 Views
Last Modified: 2012-05-12
Experts,

I need this in VB.NET, and I'm getting desperate...

This was my first attempt at this question, my own approach is a complete failure - I NEED to store the card data in the app, so as an enumeration? (the card data is static, does not change). Dictionary? Please give a complete answer...

http://www.experts-exchange.com/Programming/Languages/.NET/Q_27291428.html

This is another cross-posted version of this question I also have open, but I'm getting C# answers that I cannot use. I'm perfectly happy to award points for both (though that's prolly not allowed):

http://www.experts-exchange.com/Programming/Languages/.NET/Q_27317071.html

I have a string that looks like the following, let's call it strCards = "1,1,2,2,2,3,1,3,34,34,34,23,23,23,2,4,4,4,6,6,6,1,1,1,99,99,34,34"

This string is always comma seperated.

These are card_ids.

The card data looks like this:

id       Card Name
1          cardone
2          cardtwo
3          cardthree
4          cardfour
5          cardfive
6          cardsix
etc

I need to be able to parse the strCard and list the CardName and the number of times that card_id appears in strCards in a listbox, so:

cardone            6
cardtwo            3
cardthree          2
cardfour            3
cardsix              3
...
cardninetynine  2

and so on...

0
Comment
Question by:crafuse
  • 3
  • 2
5 Comments
 
LVL 25

Expert Comment

by:Luis Pérez
ID: 36567235
Ok, here's my solution.

I've used a ListView instead a ListBox for the results, as you can add different columns to it. So create a new ListView in your form and call it "lvwCards". Add two columns to your lvwCards ListView. First column must show the text "Card" in the header, and second column must show "Times". Set the View property of the ListView to "Details" value.

Now we're going to fill the lvwCards. Here's my code:

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Dim strCard As String = "1,1,2,2,2,3,1,3,34,34,34,23,23,23,2,4,4,4,6,6,6,1,1,1,99,99,34,34"

        'Split the string into separate numbers
        Dim cards() As String = strCard.Split(",")

        'Iterate thru the array of numbers
        For Each card As String In cards
            'Get the card name corresponding to this number
            Dim cardName As String = getCardName(card)

            'Get the item with that card name
            Dim item As ListViewItem = Me.lvwCards.FindItemWithText(cardName)

            'If the item isn't found, create a new item for this card name
            If IsNothing(item) Then
                item = Me.lvwCards.Items.Add(cardName)

                'By default, assign "0" to the number of times
                item.SubItems.Add("0")
            End If

            'Append 1 to the number of times this card appears
            item.SubItems(1).Text = (CInt(item.SubItems(1).Text) + 1).ToString
        Next
    End Sub

Open in new window


The getCardName function is as follows (obviosly I've only added card names for the card numbers you put in your example; you must fill with all the possible card name-card number pairs).

    Private Function getCardName(ByVal card As String) As String
        Select Case card
            Case "1"
                Return "cardone"
            Case "2"
                Return "cardtwo"
            Case "3"
                Return "cardthree"
            Case "4"
                Return "cardfour"
            Case "6"
                Return "cardsix"
            Case "34"
                Return "cardthirtyfour"
            Case "23"
                Return "cardtwentythree"
            Case "99"
                Return "cardninetynine"
        End Select
    End Function

Open in new window


Hope that helps. You can see a preview of the results in the attached image. Results of the code.
0
 
LVL 25

Expert Comment

by:Luis Pérez
ID: 36567247
Storing the number-name card pairs into a function is not a very elegant but working solution. Obviously there are many other methods, and you must consider them specially if is suitable that in the future more cards can appear. In that case you would need an external card data source: a database, or xml file, or INI file...
0
 

Author Comment

by:crafuse
ID: 36567604
Thanks Roland!

Perfect & simple & elegant. However, I do have need for a listbox & not a listview (which i've never used before). The reason for that is because i'm calling this routine later to populate a richtextbox. but no problem, i'll look at this tomorrow and respond.

below is my own un-expert effort. perhaps you could take a look at it - i can't seem to get the last item to be listed without that last pass through the data - what am i doing wrong?

would it be too much trouble for you to change your code for a listbox? i don't care about column alignment - i'm using fixed fonts anyways, so i can manipulate things to make it look good...

thanks...

crafuse
Public Enum Cards
        CardOne = 1
        CardTwo = 2
        CardThree = 3
        CardFour = 4
        CardFive = 5
        CardTwentyFive = 25
        CardThirtyFour = 34
        CardNinja = 99
    End Enum

    Public Function MyEnumName(ByVal EnumIndex As Cards) As String
        MyEnumName = [Enum].GetName(GetType(Cards), EnumIndex)
    End Function

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

        strLibraryList = "1,1,1,34,2,2,4,4,99,99,99,34,4,4,4,4,99,99,99,99,1,1,34,34,34,34,34,34,1,1"

        If strLibraryList <> "" Then
            Dim MyArray As New ArrayList()
            Dim values() As String = strLibraryList.ToString.Split(",")
            'Dim int As Integer = 1
            Dim int As Integer
            Dim total As Integer

            MyArray.AddRange(values)
            MyArray.Sort()

            Dim b As Integer
            For b = 0 To MyArray.Count - 1
                If MyArray(b) <> int AndAlso total > 0 Then

                    Dim CardSQL As String
                    Dim strCardName As String


                    strCardName = MyEnumName(int)

                    If strCardName <> "" Then
                        ListBox1.Items.Add(strCardName.PadRight(32, " ") & " " & total)
                    Else
                        ListBox1.Items.Add("No Cardname in DB" & " " & total)
                    End If

                    total = 1
                    int = MyArray(b)
                Else
                    total += 1
                    int = MyArray(b)
                End If
            Next b
            'here we try and capture the last item that is not being added to the listbox

            If b = MyArray.Count AndAlso total > 0 Then
                Dim CardSQL As String
                Dim strCardName As String

                
                strCardName = MyEnumName(int)

                If strCardName <> "" Then
                    ListBox1.Items.Add(strCardName.PadRight(32, " ") & " " & total)
                Else
                    ListBox1.Items.Add("No Cardname in DB" & " " & total)
                End If
                
            End If

        End If
    End Sub

Open in new window

0
 
LVL 25

Accepted Solution

by:
Luis Pérez earned 500 total points
ID: 36567759
Ok, so you need a ListBox. With this requirement my previous code does not work, because it relies directly on the ListView to find the number of times a card appears. But let's change it a bit.

Instead of that, you can use a Dictionary(Of String, Integer) to hold the cards and the number of times each card appears. This Dictionary is nothing but a collection of integer values, each one of them with a string key, so we'll use the card number (in string format) as the string key, and for each card will hold the number of times it appears.

Here's the modified code:

        Dim strCard As String = "1,1,2,2,2,3,1,3,34,34,34,23,23,23,2,4,4,4,6,6,6,1,1,1,99,99,34,34"

        'Split the string into separate numbers
        Dim cards() As String = strCard.Split(",")

        'This dictionary will hold each card and the number of times it appears
        Dim repetitions As Dictionary(Of String, Integer) = New Dictionary(Of String, Integer)

        'Iterate thru the array of numbers
        For Each card As String In cards
            'See if the card is already in the dictionary
            'If not, add a new dictionary entry with card number and 0 repetitions
            If (Not repetitions.ContainsKey(card)) Then
                repetitions.Add(card, 0)
            End If

            'Append 1 to the number of times this card appears
            repetitions.Item(card) += 1
        Next

        'Put the results in a ListBox
        For Each card As String In repetitions.Keys
            Dim cardName As String = getCardName(card)
            Dim strOutput As String = cardName + New String(" ", 25 - cardName.Length) + repetitions.Item(card).ToString
            Me.ListBox1.Items.Add(strOutput)
        Next

Open in new window


You are doing it well using an Enum to store the card number-card name pair. So you can replace my getCardName function call by your MyEnumName easily.

Hope that helps.
0
 

Author Comment

by:crafuse
ID: 36567960
Roland -

this is great. it works nice. i'll go over it in more detail tomorrow - i have to get to know the following a bit better:

Dim strOutput As String = cardName + New String(" ", 25 - cardName.Length) + repetitions.Item(card).ToString

Thanks tons,

crafuse
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Suggested Solutions

Well, all of us have seen the multiple EXCEL.EXE's in task manager that won't die even if you call the .close, .dispose methods. Try this method to kill any excels in memory. You can copy the kill function to create a check function and replace the …
Introduction As chip makers focus on adding processor cores over increasing clock speed, developers need to utilize the features of modern CPUs.  One of the ways we can do this is by implementing parallel algorithms in our software.   One recent…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now