Solved

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

Posted on 2010-08-18
30
265 Views
Last Modified: 2013-11-11
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

0
Comment
Question by:kevp75
  • 17
  • 9
  • 4
30 Comments
 
LVL 25

Author Comment

by:kevp75
Comment Utility
p.s.   There are 4 Items in n.ToString().Split("|")
0
 
LVL 52

Expert Comment

by:Carl Tawn
Comment Utility
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
 
LVL 52

Expert Comment

by:Carl Tawn
Comment Utility
p.s. nice to see you back on EE :o)
0
 
LVL 25

Author Comment

by:kevp75
Comment Utility
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
 
LVL 25

Author Comment

by:kevp75
Comment Utility
p.s.    Returns me Query2(0).Count = 0
0
 
LVL 25

Author Comment

by:kevp75
Comment Utility
you can see it here:
http://indev.zipcm.com/
0
 
LVL 25

Author Comment

by:kevp75
Comment Utility
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
 
LVL 25

Author Comment

by:kevp75
Comment Utility
DOH...  spoke too soon
0
 
LVL 52

Expert Comment

by:Carl Tawn
Comment Utility
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
 
LVL 22

Expert Comment

by:Snarf0001
Comment Utility
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
 
LVL 25

Author Comment

by:kevp75
Comment Utility
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
 
LVL 25

Author Comment

by:kevp75
Comment Utility
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
 
LVL 25

Author Comment

by:kevp75
Comment Utility
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
 
LVL 25

Author Comment

by:kevp75
Comment Utility
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
 
LVL 22

Expert Comment

by:Snarf0001
Comment Utility
Ok, and can you give a sample of the end <ul> you're trying to get this into?

0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 25

Author Comment

by:kevp75
Comment Utility
@Snarf0001   It's all in there...
0
 
LVL 22

Expert Comment

by:Snarf0001
Comment Utility
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
 
LVL 25

Author Comment

by:kevp75
Comment Utility
<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
 
LVL 22

Expert Comment

by:Snarf0001
Comment Utility
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
 
LVL 25

Author Comment

by:kevp75
Comment Utility
I'm wondering if a step could be skipped here....   how to filter that last Split?
0
 
LVL 52

Expert Comment

by:Carl Tawn
Comment Utility
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
 
LVL 22

Expert Comment

by:Snarf0001
Comment Utility
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
 
LVL 25

Author Comment

by:kevp75
Comment Utility
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
 
LVL 22

Accepted Solution

by:
Snarf0001 earned 500 total points
Comment Utility
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
 
LVL 22

Assisted Solution

by:Snarf0001
Snarf0001 earned 500 total points
Comment Utility
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
 
LVL 25

Author Comment

by:kevp75
Comment Utility
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
 
LVL 22

Expert Comment

by:Snarf0001
Comment Utility
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
 
LVL 25

Author Comment

by:kevp75
Comment Utility
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
 
LVL 22

Expert Comment

by:Snarf0001
Comment Utility
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
 
LVL 25

Author Comment

by:kevp75
Comment Utility
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

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Suggested Solutions

In my previous article (http://www.experts-exchange.com/Programming/Languages/.NET/.NET_Framework_3.x/A_4362-Serialization-in-NET-1.html) we saw the basics of serialization and how types/objects can be serialized to Binary format. In this blog we wi…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
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…

728 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

11 Experts available now in Live!

Get 1:1 Help Now