'Index was outside the bounds of the array.' Issue in LINQ Query From Array

I am getting an 'Index was outside the bounds of the array.' Error in Query2

Can you see why?


Dim Query1 = From n In str.Split(",")
            tmpNav.Append("<ul>" & vbCrLf)
            For Each n In Query1
                If ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5}) Then
                    Dim Query2 = From nl In n.ToString().Split("|") Where nl(1) = "0" And (nl(2) = "1" Or nl(2) = "2")
                    tmpNav.Append("<li class=""site_nav"">" & Query2.Count & "</li>" & vbCrLf)
                ElseIf Not (ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5})) Then
                    Dim Query2 = From nl In n.ToString().Split("|") Where nl(1) = "0" And (nl(2) = "0" Or nl(2) = "2")
                    tmpNav.Append("<li class=""site_nav"">" & Query2.Count & "</li>" & vbCrLf)
                Else
                    Dim Query2 = From nl In n.ToString().Split("|") Where nl(1) = "0" And (nl(2) = "2")
                    tmpNav.Append("<li class=""site_nav"">" & Query2.Count & "</li>" & vbCrLf)
                End If
            Next
            tmpNav.Append("</ul>" & vbCrLf)

Open in new window

LVL 25
kevp75Asked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
Snarf0001Connect With a Mentor Commented:
Sorry on that last post, still had testing data in in place of the Zip.Security:
        Dim str As String = "178|0|2|Home,182|0|2|Sitemap,184|0|0|Login,185|0|0|Register,186|0|1|Logout,187|0|1|Profile,192|0|1|Change Password"

        'get the full list into a multidimensional array that you can query the sub-parts of
        Dim itemArray = From n In str.Split(",") Select n.Split("|")
        'ALL paths you had were filtering off of the menuItem(1) = 0 as it was, so do it first
        Dim query = From menuItem In itemArray Where menuItem(1) = "0"

        If (ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5}) Then
            query = query.Where(Function(menuItem) menuItem(2) = "1" Or menuItem(2) = "2")
        ElseIf Not (ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5})) Then
            query = query.Where(Function(menuItem) menuItem(2) = "0" Or menuItem(2) = "2")
        Else
            query = query.Where(Function(menuItem) menuItem(2) = "2")
        End If

        tmpNav.Append("<ul>" & vbCrLf)
        For Each matchedItem In query
            tmpNav.Append("<li class=""site_nav"">" & matchedItem(3) & "</li>" & vbCrLf)
        Next
        tmpNav.Append("</ul>" & vbCrLf)

Open in new window

0
 
kevp75Author Commented:
p.s.   There are 4 Items in n.ToString().Split("|")
0
 
Carl TawnSystems and Integration DeveloperCommented:
Possibly a subscript issue? Arrays in VB.Net start at zero (unless you are intentionally checking the second and third elements!).

If that's not the issue could you post a sample of the data that might be in n?
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
Carl TawnSystems and Integration DeveloperCommented:
p.s. nice to see you back on EE :o)
0
 
kevp75Author Commented:
Hey carl :)

n = 178|0|2|Home,182|0|2|Sitemap,184|0|0|Login,185|0|0|Register,186|0|1|Logout,187|0|1|Profile,192|0|1|Change Password

New code...   (gets the 7 items in the comma-delimited list split)
Dim Query1 = From n In str.Split(",")
            tmpNav.Append("<ul>" & vbCrLf)
            For i As Integer = 0 To Query1.Count - 1
                If ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5}) Then
                    Dim Query2 = From nl In Query1.ToString().Split("|") Where nl(1) = "0" And (nl(2) = "1" Or nl(2) = "2")
                    tmpNav.Append("<li class=""site_nav"">" & Query2(0).ToString() & "</li>" & vbCrLf)
                ElseIf Not (ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5})) Then
                    Dim Query2 = From nl In Query1.ToString().Split("|") Where nl(1) = "0" And (nl(2) = "0" Or nl(2) = "2") Select nl
                    tmpNav.Append("<li class=""site_nav"">" & Query2(0).Count & "</li>" & vbCrLf)
                Else
                    Dim Query2 = From nl In Query1(i).ToString().Split("|") Where nl(1) = "0" And (nl(2) = "2")
                    tmpNav.Append("<li class=""site_nav"">" & Query2(0).ToString() & "</li>" & vbCrLf)
                End If
            Next
            tmpNav.Append("</ul>" & vbCrLf)

Open in new window

0
 
kevp75Author Commented:
p.s.    Returns me Query2(0).Count = 0
0
 
kevp75Author Commented:
you can see it here:
http://indev.zipcm.com/
0
 
kevp75Author Commented:
I think I may have figured it out...


Dim Query2 = From nl In Query1 Let l = nl.Split("|") Where l(1) = "0" And (l(2) = "0" Or l(2) = "2") Select nl

Open in new window

0
 
kevp75Author Commented:
DOH...  spoke too soon
0
 
Carl TawnSystems and Integration DeveloperCommented:
What is it that you are trying to get at?  Are you trying to pick out one piece of information from the string based on the values of the other elements?
0
 
Snarf0001Commented:
Question, you have 2 different code segments posted here.

In the code in one of your responses "New code...   (gets the 7 items in the comma-delimited list split)"...
you have written
  Dim Query2 = From nl In Query1.ToString().Split("|")

That should be From nl in n.ToString()... not Query1.ToString(), otherwise you're going to be calling the split("|") on the .ToString() of Query1, which would be something like "System.Linq.IEnumberable....."
0
 
kevp75Author Commented:
Ok...  so when I do this:

                    For Each Item In Query2
                        tmpNav.Append("<li class=""site_nav"">" & Item(3) & "</li>" & vbCrLf)
                    Next

I get what is needed just multipled 7 times (due to the 7 items in n)

When I change it to:

                    'For Each Item In Query2
                    tmpNav.Append("<li class=""site_nav"">" & Query2(3).ToString & "</li>" & vbCrLf)
                    'Next


I get 7 System.String[]'s

???
0
 
kevp75Author Commented:
Essentially what I am trying to do is get a sites navigation from a comma delimited list.

Each Item in the comma delimited list is delimited with a |

So...  there are 7 items in the first interation, and 4 each thereafter


Dim Query1 = From n In str.Split(",")
            tmpNav.Append("<ul>" & vbCrLf)
            For i As Integer = 0 To Query1.Count - 1
                If ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5}) Then
                    Dim Query2 = From nl In Query1 Let l = nl.Split("|") Where nl(1) = "0" And (nl(2) = "1" Or nl(2) = "2") Select l
                    tmpNav.Append("<li class=""site_nav"">" & Query2.Count & "</li>" & vbCrLf)
                ElseIf Not (ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5})) Then
                    Dim Query2 = From nl In Query1 Let l = nl.Split("|") Where l(1) = "0" And (l(2) = "0" Or l(2) = "2") Select l
                    'For Each Item In Query2
                    tmpNav.Append("<li class=""site_nav"">" & Query2.Count & "</li>" & vbCrLf)
                    'Next
                Else
                    Dim Query2 = From nl In Query1 Let l = nl.Split("|") Where nl(1) = "0" And (nl(2) = "2") Select l
                    tmpNav.Append("<li class=""site_nav"">" & Query2.Count & "</li>" & vbCrLf)
                End If
            Next
            tmpNav.Append("</ul>" & vbCrLf)

Open in new window

0
 
kevp75Author Commented:
Actually...  What I really should be doing is a Join on the first query, that way I always only get what I am after, instead of getting everything...

But, how would I do that  Select From One Split(",") Join another Split("|")
0
 
kevp75Author Commented:
the test data is:

178|0|2|Home,182|0|2|Sitemap,184|0|0|Login,185|0|0|Register,186|0|1|Logout,187|0|1|Profile,192|0|1|Change Password
0
 
Snarf0001Commented:
Ok, and can you give a sample of the end <ul> you're trying to get this into?

0
 
kevp75Author Commented:
@Snarf0001   It's all in there...
0
 
Snarf0001Commented:
No no, I mean I don't quite understand what you're trying to achieve, can you write out how you want the end result to look based on that sample data, ie:

<ul>
  <li class="samplecode">5</li>
</ul>

Or explain what each of the separated columns are supposed to represent.
0
 
kevp75Author Commented:
<ul>
<li class="site_nav">Link 1</li>
<li class="site_nav">Link 2</li>
<li class="site_nav">Link 3</li>
<li class="site_nav">Link 4</li>
<li class="site_nav">Link 5</li>
<li class="site_nav">Link 6</li>
<li class="site_nav">Link 7</li>
</ul>
0
 
Snarf0001Commented:
Ok, IF I understand, it's the logic flow you're just a little bit off on.
Rather than trying to split everything on subsequent queries, you should be splitting BOTH parts off right off the start into a multidimensional array, so you can query the subparts (0, 1, 2, etc) in the further queries.

Not sure what the security checks shoudl be doing (as they're the same), but give this a shot:

        Dim str As String = "178|0|2|Home,182|0|2|Sitemap,184|0|0|Login,185|0|0|Register,186|0|1|Logout,187|0|1|Profile,192|0|1|Change Password"

        'get the full list into a multidimensional array that you can query the sub-parts of
        Dim itemArray = From n In str.Split(",") Select n.Split("|")

        tmpNav.Append("<ul>" & vbCrLf)
        If (ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5}) Then
            'now make another query to filter the items on the sub-parts
            Dim q2 = From menuItem In itemArray Where menuItem(1) = "0" And (menuItem(2) = "1" Or menuItem(2) = "2")
            'and render out only the matched items
            For Each matchedItem In q2
                tmpNav.Append("<li class=""site_nav"">" & matchedItem(3) & "</li>" & vbCrLf)
            Next
        ElseIf Not (ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5})) Then
            Dim q2 = From menuItem In itemArray Where menuItem(1) = "0" And (menuItem(2) = "0" Or menuItem(2) = "2")
            For Each matchedItem In q2
                tmpNav.Append("<li class=""site_nav"">" & matchedItem(3) & "</li>" & vbCrLf)
            Next
        Else
            Dim q2 = From menuItem In itemArray Where menuItem(1) = "0" And menuItem(2) = "2"
            For Each matchedItem In q2
                tmpNav.Append("<li class=""site_nav"">" & matchedItem(3) & "</li>" & vbCrLf)
            Next
        End If
        tmpNav.Append("</ul>" & vbCrLf)

Open in new window

0
 
kevp75Author Commented:
I'm wondering if a step could be skipped here....   how to filter that last Split?
0
 
Carl TawnSystems and Integration DeveloperCommented:
Or something like:
            Dim Query1 = From n In Str.Split(",") Select n
            Dim Query2

            tmpNav.Append("<ul>" & vbCrLf)

            If ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5}) Then
                Query2 = (From nl In Query1
                                 Let n = nl.ToString().Split("|") Where n(1) = "0" And (n(2) = "1" Or n(2) = "2")
                                 Select n(3))
            ElseIf ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5}) Then
                Query2 = (From nl In Query1
                                 Let n = nl.ToString().Split("|") Where n(1) = "0" And (n(2) = "0" Or n(2) = "2")
                                 Select n(3))
            Else
                Query2 = (From nl In Query1
                             Let n = nl.ToString().Split("|") Where n(1) = "0" And n(2) = "1"
                             Select n(3))
            End If

            For Each result In Query2
                tmpNav.Append("<li class=""site_nav"">" & result.ToString() & "</li>" & vbCrLf)
            Next

            tmpNav.Append("</ul>" & vbCrLf)

Open in new window

0
 
Snarf0001Commented:
Well, the 2nd split is the one that separates the data you're actually filtering on.  You're doing it in every conditional flow after that, so it makes more sense to do it up front.

But here would be a more optimized way of doing it:
        Dim str As String = "178|0|2|Home,182|0|2|Sitemap,184|0|0|Login,185|0|0|Register,186|0|1|Logout,187|0|1|Profile,192|0|1|Change Password"

        'get the full list into a multidimensional array that you can query the sub-parts of
        Dim itemArray = From n In str.Split(",") Select n.Split("|")
        'ALL paths you had were filtering off of the menuItem(1) = 0 as it was, so do it first
        Dim query = From menuItem In itemArray Where menuItem(1) = "0"

        If (tempval = True) Then
            query = query.Where(Function(menuItem) menuItem(2) = "1" Or menuItem(2) = "2")
        ElseIf Not tempval = True Then
            query = query.Where(Function(menuItem) menuItem(2) = "0" Or menuItem(2) = "2")
        Else
            query = query.Where(Function(menuItem) menuItem(2) = "2")
        End If

        tmpNav.Append("<ul>" & vbCrLf)
        For Each matchedItem In query
            tmpNav.Append("<li class=""site_nav"">" & matchedItem(3) & "</li>" & vbCrLf)
        Next
        tmpNav.Append("</ul>" & vbCrLf)

Open in new window

0
 
kevp75Author Commented:
tried something similar to that carl, but I kept getting 7x4 items displayed...

so far Snarf0001's seems to work, however, I would like to know if the 2 queries could be combined into one...

I imaginge that would be more efficient...
0
 
Snarf0001Connect With a Mentor Commented:
Keep in mind that since LINQ uses deferred execution, you can tack on where clauses at any point before the final execution, and the processor is still only going to query the data ONCE.
0
 
kevp75Author Commented:
do you think it would be faster if I use Linq to process this, or simply use the arrays I would get from Splitting the string and processing it that way?
0
 
Snarf0001Commented:
Performance-wise doubt there would be any real difference.

From a programming perspective I far prefer the linq approach, it's much more consise and easy to read and follow than a series of ifs / switches and fors that would be required to do it the other way.
0
 
kevp75Author Commented:
Ok...  for some reason
                Return query.Count
                If (ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5})) Then
                    query = query.Where(Function(menuItem) menuItem(2) = 1 Or menuItem(2) = 2)
                ElseIf Not (ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5})) Then
                    query = query.Where(Function(menuItem) menuItem(2) = 0 Or menuItem(2) = 2)
                Else
                    query = query.Where(Function(menuItem) menuItem(2) = 2)
                End If

returns 7, but

                Dim query = From menuItem In itemArray Where menuItem(1) = 0
                If (ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5})) Then
                    query = query.Where(Function(menuItem) menuItem(2) = 1 Or menuItem(2) = 2)
                ElseIf Not (ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5})) Then
                    query = query.Where(Function(menuItem) menuItem(2) = 0 Or menuItem(2) = 2)
                Else
                    query = query.Where(Function(menuItem) menuItem(2) = 2)
                End If
                Return query.Count

returns nothing....
0
 
Snarf0001Commented:
Not sure why, given the test string you provided:
"178|0|2|Home,182|0|2|Sitemap,184|0|0|Login,185|0|0|Register,186|0|1|Logout,187|0|1|Profile,192|0|1|Change Password"

every path of the if statement returns items.
Please post more complete code, may be a problem somewhere else, and explain what the ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5}))  is supposed to do.
0
 
kevp75Author Commented:
ZipCM.Security.CanAccess(New Integer() {1, 2, 3, 4, 5})  returns a boolean value to determine whether a certain user type can access that particular part of the code.

i think that is where it'w at.....   it was working unil i switched some stuff...

thanks for the help
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.