Results 1 to 11 of 11

Thread: [RESOLVED] How to address elements in a SortedList Array?

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Nov 2016
    Posts
    125

    Resolved [RESOLVED] How to address elements in a SortedList Array?

    How does one access the elements of a SortedList? The ‘ .Contains’ property does the locating but the second element ‘ .Item’ property yields an error message BC30512: Option Strict On disallows implicit conversions from 'Object' to 'Decimal'. Is there another property to replace the '.Item'?
    All of the sample coding I research do not address the second element [Capacity, Count, Add, Clear, Contains,ContainsValue, Item(key), Remove(Key) and RemoveAT(Index)]. TIA JP

    Code:
        Private PovertyGuidelines As SortedList
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    
            ' Create Guidelines and intialize beginning values.
            PovertyGuidelines = New SortedList From {{"1", "10210"}, {"2", "13690"},
            {"3", "17170"}, {"4", "20650"}, {"5", "24130"}, {"6", "27610"}, {"7", "31090"},
            {"8", "34570"}, {"9", "38050"}, {"10", "41530"}, {"11", "45010"}, {"12", "48490"}}
        End Sub
    
                If PovertyGuidelines.Contains(IndividualHousehold.FamilySize) Then
    
    
                    PovertyLevelDecimal = PovertyGuidelines.Item(IndividualHousehold.FamilySize)
                    If PovertyLevelDecimal >= IndividualHousehold.IncomeSize Then

  2. #2
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: How to address elements in a SortedList Array?

    SortedList is the non-generic version of the type, so all of its items are of type Object and you have to use a cast operator like CType() if you want to use them as a more specific type.

    What you want is the generic SortedList(Of TKey, TValue) class. From the looks of your data, you want SortedList(Of String, String). The generic type parameters tell VB which type to make the key and value properties.

    Probably your next problem is it looks like you intend for the values to be Decimal, but for some reason you've specified them as Strings. Is there a reason?
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Nov 2016
    Posts
    125

    Re: How to address elements in a SortedList Array?

    Thanks for the reply. I tried several code changes and missed returning the string to Decimal. Your reply helped me to discover the following code correction:
    Code:
    CDec(PovertyGuidelines.Item(IndividualHousehold.FamilySize))
    and I was able to successfully execute it.Then in a second procedure, I ran into a baffling 'exception handle error' on first if statement having copied the same code into the new procedure. TIA JP
    Code:
      If PovertyGuidelines.Contains(IndividualHousehold.FamilySize) Then
                    PovertyLevelDecimal = CDec(PovertyGuidelines.Item(IndividualHousehold.FamilySize))
                    If PovertyLevelDecimal < IndividualHousehold.IncomeSize Then
    
                        ' search for households with income below poverty level.
                        BelowPovertyLevelCountInteger += 1
                        LoopCountInteger += 1
                        If MaxIndexInterger = LoopCountInteger - 1 Then
                            Exit For
    
                        End If
                    End If

  4. #4
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: How to address elements in a SortedList Array?

    Exceptions are like messages from the gods. They have a name, like "IndexOutOfRangeException" that helps you figure out what kind of error you caused. More importantly, they have a message, that will say something like, "The index '3' was not in the array." Most of the time if you read them, it's pretty clear what's going on. Some of them seem a little cryptic until you've seen them a few times.

    So you should really post the name of the exception you got, and the message it told you. If you don't understand it, I'm pretty sure someone here can.

    One trick: if the exception is "TargetInvocationException", that one is tricky. It's not the real problem. You need to look at its InnerException property. That's the real one. Sometimes THAT'S a TargetInvocationException. Keep going until you find the real exception.

    Here's the problem: Contains() is a LINQ method, not one built-in to SortedList. SortedList isn't really a list of your items, internally. It's a list of a type called KeyValuePair. So using LINQ's Contains() with SortedList isn't often very useful. You should really be using the List's ContainsKey() method, which takes the key value. But if you keep using the non-generic type you'll probably find more and more problems.

    Here's a quick demo of how I'd set up a SortedList(Of Decimal, Decimal), I think it'd be more handy than what you're doing:
    Code:
    Imports System
    Imports System.Threading.Tasks
    Imports System.Collections.Generic
    Imports System.Linq
    				
    Public Module Module1
    	Public Sub Main()
    		Dim sorted As New SortedList(Of Decimal, Decimal) From {
    			{ 10, 1023456 },
    			{ 5, 5432 },
    			{ 8, 891011 }
    		}
    		
    		Dim povertyLevel As Decimal = 30000
    		Dim hasHousehold As Decimal = 10
    		Dim notHousehold As Decimal = 15
    	
    		
    		If sorted.ContainsKey(hasHousehold) Then
    			If sorted(hasHousehold) < povertyLevel Then
    				Console.WriteLine("Household {0} is below the level!", hasHousehold)
    			End If
    		End If
    		
    		If sorted.ContainsKey(notHousehold) Then
    			If sorted(notHousehold) < povertyLevel Then
    				Console.WriteLine("Household {0} is below the level!", hasHousehold)
    			End If
    		End If
    	End Sub
    
    End Module
    The more casts you have to do, the harder you have to think about every line. Imagine trying to win a game of checkers if you have glasses that make all the pieces look the same color. You'd have to start every move by asking questions about the color of each piece. That's what programming with non-generic types is like.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  5. #5

    Thread Starter
    Lively Member
    Join Date
    Nov 2016
    Posts
    125

    Re: How to address elements in a SortedList Array?

    Thanks for the reply; I had to take a break to accomplish some household chores.
    I erred in saying one procedure worked and the other did not - due to wrong procedure call.
    I changed my code to using 'ContainsKey', Verified that the index 'IndividualHousehold.FamilySize' was operating coprrectly but again an exception occurs on the sorted array: 'exception {"Failed to compare two elements in the array."} System.InvalidOperationException'. Argument exception: Object must be of type String! I'm at a loss on how work around this exception. TIA JP

  6. #6
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: How to address elements in a SortedList Array?

    I'm at a disadvantage here, you didn't post your new code. If you caused the problem with code similar to your original code, I'm going to repeat myself:

    The more casts you have to do, the harder you have to think about every line. Imagine trying to win a game of checkers if you have glasses that make all the pieces look the same color. You'd have to start every move by asking questions about the color of each piece. That's what programming with non-generic types is like.
    Everything in your SortedList is of type Object right now. Reality is they're all Strings wearing an Object mask. But it seems like your code really wants to be working with numeric types like Decimal, so you're using cast operators like CDec() here and there to convert when needed.

    The exception tells me two pieces of information:
    • The failure happened when trying to manipulate the array, because sorting requires comparison.
    • The problem is one item was not a String, and another item was a String.

    So you probably messed up and tried to add a Decimal, not a String, to the array. This worked, at first, because the rules of the game say anything can wear a mask that makes it an Object. But then the SortedList needed to sort itself, and eventually it had to compare the Decimal to a String. While we, as humans, can come up with sensible answers for how that might work, the rules SortedList follows don't have an answer, so it fails.

    The most correct thing to do would be to decide if you want Decimals or Strings and stick with the one you need. Then, you should use SortedList(Of String, String) or SortedList(Of Decimal, Decimal) like I did in #4. That will ensure that if you mess up and try to put the wrong thing in the list, you get a failure at compile time instead of run time, which is easier to figure out and fix.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  7. #7

    Thread Starter
    Lively Member
    Join Date
    Nov 2016
    Posts
    125

    Re: How to address elements in a SortedList Array?

    Would I be better served by not using SortedList? If the array { "persons in household" , "household income" } is inserted in sorted sequence by 'persons in household' then I could do a loop search to obtain the poverty level Household Income for comparison the survey data! Or is there a simple code change around my problem? TIA JP

  8. #8

    Thread Starter
    Lively Member
    Join Date
    Nov 2016
    Posts
    125

    Re: How to address elements in a SortedList Array?

    Thanks for the reply. I will redeclare the sortedlist and see what I run into. Your insight is greatly appreciated. Thanks again. JP

  9. #9
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: How to address elements in a SortedList Array?

    Quote Originally Posted by justphilip View Post
    Would I be better served by not using SortedList? If the array { "persons in household" , "household income" } is inserted in sorted sequence by 'persons in household' then I could do a loop search to obtain the poverty level Household Income for comparison the survey data! Or is there a simple code change around my problem? TIA JP
    I can't see your code so I can't comment, but my guess is you don't really want either of those things to be Strings. You probably read them in from a file, but they're ultimately numbers so after you get them from the file you should convert them to numbers, THEN put them in the list.

    Generally the right steps for dealing with file data is:
    1. Read the string data.
    2. Convert the data to a more convenient format.
    3. Operate on the converted data.
    4. Convert the data back to strings.
    5. Write the strings to the file.


    If you try to keep it as strings everywhere, it's hard to keep track of when it should be converted to what, and it's easier to make mistakes.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  10. #10

    Thread Starter
    Lively Member
    Join Date
    Nov 2016
    Posts
    125

    Re: How to address elements in a SortedList Array?

    Thanks for the reply. I've been stuck on my first array project and am feeling discouraged! The problem is how to load data into a two element structure and be able to address the individual elements.
    Code:
    Public Structure SurveyData
            Public HeadCountDecimal() As Decimal
            Public PovertyIncomeDecimal() As Decimal
    End Structure
    Private MyIndexInterger As Integer
    Private MaxIndexInterger As Integer
    Trying to load data into Structure SurveyData to effect what the commented out PovertyGuidelines SortList accomplished. Below I attempted two different approaches – both failures. Loading data into this structure should be simple, but the techniques has escaped me. I sure could use a reference on the subject!

    Code:
      '    PovertyGuidelines = New SortedList From {{"1", "10210"}, {"2", "13690"},
        '       {"3", "17170"}, {"4", "20650"}, {"5", "24130"}, {"6", "27610"}, {"7", "31090"},
        '       {"8", "34570"}, {"9", "38050"}, {"10", "41530"}, {"11", "45010"}, {"12", "48490"}}
    
        'Dim LHeadCountDecimal(12) As SurveyData
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim LoadSurvey(12) As SurveyData
    
            MaxIndexInterger = 12
    
            Do Until MyIndexInterger > MaxIndexInterger
                LoadSurvey.HeadCountDecimal(MyIndexInterger) = (MyIndexInterger)
                SurveyData.PovertyIncomeDecimal(MyIndexInterger) = 6730 + 3480 * MyIndexInterger
            Loop
    
    
        End Sub
    Errors:
    Severity Code Description Project File Line Suppression State
    Error BC30456 'HeadCountDecimal' is not a member of 'Form1.SurveyData()'. Programming Exercise 8pt1pt1 D:\Documents\Visual Studio 2017\Projects\Programming Exercise 8pt1pt1\Programming Exercise 8pt1\Form1.vb 53 Active
    Error BC30469 Reference to a non-shared member requires an object reference. Programming Exercise 8pt1pt1 D:\Documents\Visual Studio 2017\Projects\Programming Exercise 8pt1pt1\Programming Exercise 8pt1\Form1.vb 54 Active

    TIA JP
    Last edited by justphilip; Apr 14th, 2017 at 01:21 PM.

  11. #11
    Super Moderator si_the_geek's Avatar
    Join Date
    Jul 2002
    Location
    Bristol, UK
    Posts
    41,929

    Re: How to address elements in a SortedList Array?

    LoadSurvey is an array, so to refer to an element within it you need brackets and some kind of number (either hard coded, or using a variable). Any properties/fields of the element (such as HeadCountDecimal) appear after those brackets.

    As such, instead of this:
    Code:
    LoadSurvey.HeadCountDecimal(MyIndexInterger)
    ...you should have something like this:
    Code:
    LoadSurvey(1).HeadCountDecimal(MyIndexInterger)
    ...where 1 should probably be a variable.


    You currently have HeadCountDecimal set to be an array each time, which probably isn't what you wanted (based on things above, it seems you want each LoadSurvey to have one HeadCountDecimal and one PovertyIncomeDecimal. If that is the case, remove the brackets from the Structure:
    Code:
    Public Structure SurveyData
            Public HeadCountDecimal As Decimal
            Public PovertyIncomeDecimal As Decimal
    End Structure

    Based on the above and a couple of other assumptions, I think this is how you want Form1_Load:
    Code:
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim LoadSurvey(12) As SurveyData
    
            MaxIndexInterger = 12
    
            For MyIndexInterger = 0 To MaxIndexInterger
                LoadSurvey(MyIndexInterger).HeadCountDecimal = MyIndexInterger
                LoadSurvey(MyIndexInterger).PovertyIncomeDecimal = 6730 + 3480 * MyIndexInterger
            Next
    
        End Sub

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width