Welcome guest. Before posting on our computer help forum, you must register. Click here it's easy and free.

Author Topic: [VB .Net] Pick a random entry in a List(string)  (Read 19515 times)

0 Members and 1 Guest are viewing this topic.

liambiscuit

    Topic Starter


    Hopeful

    [VB .Net] Pick a random entry in a List(string)
    « on: July 12, 2009, 10:18:06 PM »
    Pretty much I have:

    Code: [Select]
    Dim li as List(string)
    li.add("I'm good")
    li.add("I'm better")
    li. add("I'm best")

    How do i randomly select one of these entries?
    " When the rich wage war its the Poor who die "
            Linkin Park



    Whoever said that nothing is impossible has obviously never tried to slam a revolving door. -- Lauren

    You cannot buy your friends but you can buy them pizza - AzureBlade49

    BC_Programmer


      Mastermind
    • Typing is no substitute for thinking.
    • Thanked: 1140
      • Yes
      • Yes
      • BC-Programming.com
    • Certifications: List
    • Computer: Specs
    • Experience: Beginner
    • OS: Windows 11
    Re: [VB .Net] Pick a random entry in a List(string)
    « Reply #1 on: July 13, 2009, 12:30:22 AM »
    Code: [Select]
    li.Item(Int(Rnd() * (li.Count - 1)))

    will pick a random item.
    I was trying to dereference Null Pointers before it was cool.

    liambiscuit

      Topic Starter


      Hopeful

      Re: [VB .Net] Pick a random entry in a List(string)
      « Reply #2 on: July 13, 2009, 07:54:13 PM »
      I ever told you, BC_Programmer, I love you ;)

      Another quick question --

      If i have the code:
      Code: [Select]
      Dim di As New IO.DirectoryInfo("C:\music")
      How do i get di to include all sub-directories?
      " When the rich wage war its the Poor who die "
              Linkin Park



      Whoever said that nothing is impossible has obviously never tried to slam a revolving door. -- Lauren

      You cannot buy your friends but you can buy them pizza - AzureBlade49

      BC_Programmer


        Mastermind
      • Typing is no substitute for thinking.
      • Thanked: 1140
        • Yes
        • Yes
        • BC-Programming.com
      • Certifications: List
      • Computer: Specs
      • Experience: Beginner
      • OS: Windows 11
      Re: [VB .Net] Pick a random entry in a List(string)
      « Reply #3 on: July 13, 2009, 08:02:44 PM »
      Code: [Select]
      Sub Main()


              Dim dirs As IO.DirectoryInfo()
              Dim loopdir As IO.DirectoryInfo
              dirs = New IO.DirectoryInfo("C:\music").GetDirectories
              For Each loopdir In dirs
                  Console.WriteLine(loopdir.FullName)


              Next
              Console.ReadKey()
          End Sub



      It's a bit more involved; in this case I didn't bother storing a directoryInfo for the "C:\Music" directory, rather opting to directly acquire it's subdirs. The "GetDirectories" Method of the DirecoryInfo Class returns an array of DirectoryInfo classes that you can enumerate using a For...Each Loop; in my example above it simply prints off each directory name, but you can do whatever you wish with them.
      I was trying to dereference Null Pointers before it was cool.

      finchy109



        Newbie

        • Experience: Experienced
        • OS: Windows 7
        Re: [VB .Net] Pick a random entry in a List(string)
        « Reply #4 on: April 10, 2013, 08:52:04 AM »
        I realise this is an old thread but I was wondering what  ('* li.Count - 1)))' did in the code above.....

        BC_Programmer


          Mastermind
        • Typing is no substitute for thinking.
        • Thanked: 1140
          • Yes
          • Yes
          • BC-Programming.com
        • Certifications: List
        • Computer: Specs
        • Experience: Beginner
        • OS: Windows 11
        Re: [VB .Net] Pick a random entry in a List(string)
        « Reply #5 on: April 10, 2013, 11:15:38 PM »
        I realise this is an old thread but I was wondering what  ('* li.Count - 1)))' did in the code above.....
        the value used is li.Count-1 because the Items Accessor is zero-based. However, even so there is actually a bug in the original solution that prevents the last element of a list from ever being chosen.

        It's actually a bug, somewhat. I used -1 because the Item accessor method takes a zero-based index and li.Count retrieves the total number of elements, so a 4-item list would return 4 for Count, but the fourth item would be accessed with li.Items(3).

        However, the "bug" is because rnd returns a number between 0 and 1 exclusive- that is, the resulting value will never be 1. The Int function truncates the value, so the resulting index will never actually be the last index of the list.

        The bugfix would be to use Math.Round instead of Int():

        Code: [Select]
        li.Item(Math.Round(Rnd() * (li.Count - 1)))


        Full disclosure, I didn't actually use the original code, so it wasn't fully tested. My preferred method of choosing an Item from an Array or other collection is a Generic Method I wrote in C#.

        To make ammends for my 4 year old transgression, I will post that here, after porting it to VB.NET. The original C# implementation was called "Choose" and so was my VB.NET version until I noticed the existence of the legacy Choose() Function from VB6, when I renamed it to "Pick":

        Code: [Select]
            Public Function Pick(Of T)(ChooseArray As IEnumerable(Of T)) As T
                If rgen Is Nothing Then rgen = New Random()

                Dim sorttest As SortedList(Of Double, T) = New SortedList(Of Double, T)()
                For Each loopvalue As T In ChooseArray
                    Dim rgg As Double = rgen.NextDouble()
                    Do While sorttest.ContainsKey(rgg)
                        rgg = rgen.NextDouble()
                    Loop
                    sorttest.Add(rgg, loopvalue)

                Next

                Return sorttest.First().Value
            End Function

        As a generic method, it works with an Array of Any type, and Any collection, because it accepts any IEnumerable implementation.

        If one is targeting VB11, you can even use the ported version of the method that acts as an Iterator Method:

        Code: [Select]
            Public Iterator Function Pick(Of T)(ChooseArray As IEnumerable(Of T), NumItems As Integer) As IEnumerable(Of T)
                If rgen Is Nothing Then rgen = New Random()

                Dim sorttest As SortedList(Of Double, T) = New SortedList(Of Double, T)()
                Dim ResultTest As List(Of T) = New List(Of T)

                For Each loopvalue As T In ChooseArray
                    Dim rgg As Double = rgen.NextDouble()
                    Do While sorttest.ContainsKey(rgg)
                        rgg = rgen.NextDouble()
                    Loop
                    sorttest.Add(rgg, loopvalue)

                Next

                Dim I As Integer

                Dim DictEnumerator As IEnumerator(Of KeyValuePair(Of Double, T)) = sorttest.GetEnumerator()

                Do While DictEnumerator.MoveNext() And NumItems > (I)
                    Yield DictEnumerator.Current.Value
                    I = I + 1
                Loop

            End Function

        The test Code I used that shows these methods being used:
        Code: [Select]
          Sub Main()

                Dim SelectFrom As Integer() = Enumerable.Range(0, 100).ToArray()
                For I As Integer = 0 To 100
                    Console.WriteLine(Pick(SelectFrom))
                Next

                For I As Integer = 0 To 100

                    For Each iterate In Pick(SelectFrom, 4)
                        Console.Write(Str(iterate) + ",")
                    Next
                    Console.WriteLine()

                Next

                Console.ReadKey()
            End Sub

        I was trying to dereference Null Pointers before it was cool.