tags:

views:

150

answers:

3

Hi,

I have a List of Lat/Lon co-ordinates that I'm processing in a while(true) loop. During the loop I'm building a query that will be sent to a remote service for processing. The remote service can only accept 12 pairs of Lat/Lon co-ordinates, however my list may contain several thousand. What I want to do is build the query and then send it for processing every 12 loops.

List<string[]> lList = FromDB();

int i = 0;
int intLastIndex - lList.Count;
string strQuery = String.Empty

while(true)
{
    strQuery = lList[i][0] + "|" + lList[i][1];

    if(((i % 11) == 0) && (i != 0))
    {
        SendToRemoteService(strQuery);
        strQuery = String.Empty;
    }

    if(i == intLastIndex)
    {
        break;
    }

    i++
}

However this generate an array out of bounds exception and will not process all records. Can anyone suggest a better approach?

Mark

+3  A: 

The Count function will return the total number of items in your list while the [] accessor starts at 0 so your list will work if you make the following change

int intLastIndex - lList.Count;

To

int intLastIndex =  lList.Count == 0 ? 0 : lList.Count-1;
RHicke
you are right, I found another mistake in his code too
Jader Dias
your correction alone won't prevent an exception when the length is 0
Jader Dias
the problem isn't the line, the problem is the `while(true)` thing, it has to be replaced by a `while(i < intLastIndex)` or a `for` at least
Jader Dias
+3  A: 

You also need a final "SendToRemoteService" call after the loop if the strQuery is not empty after the exit.

Daver
you are right, I found another mistake in his code too
Jader Dias
Nice answer. I was thinking of trying a linq solution, but I'm still too green at it.
Daver
+8  A: 

I have found at least 5 bugs in your code, you should rewrite it to:

List<string[]> lList = FromDB();
List<string> query = new List<string>();
for(int i = 0; i < lList.Count; i++)
{
    query.Add(lList[i][0] + "|" + lList[i][1]);

    if((((i + 1) % 12) == 0) || (i == (lList.Count - 1)))
    {
        SendToRemoteService(String.Join("|", query.ToArray()));
        query.Clear();
    }
}

But if you want to upgrade to C# 3.0 you can use System.Linq, aka Linq-to-objects, which will simplify your code. Imagine you would want to send a single pair per request, then your code would be:

List<string[]> lList = FromDB();
var queries = lList
    .Select(latlon => String.Format("{0}|{1}", latlon[0], latlon[1]));
foreach(var query in queries)
{
    SendToRemoteService(query);
}

Now grouping into groups of 12 pairs:

List<string[]> lList = FromDB();
var queries = lList
    .Select((latlon, index) => new { latlon, index })
    .GroupBy(item => item.index / 12, item => item.latlon)
    .Select(group => String.Join("|", 
         group.Select(latlon =>  String.Format("{0}|{1}", latlon[0], latlon[1]))
              .ToArray()
     ));
foreach(var query in queries)
{
    SendToRemoteService(query);
}

code style note: many people would rather use query instead of strQuery as a variable name.

Jader Dias
Every time I think I got it right I see another bug
Jader Dias
We should use TDD for this =)
Jader Dias
By using the GroupBy statement you are going to have all the data in memory (take care of your memory;))
Maghis
List<string[]> lList = FromDB(); don't mind my comment, everything is already in memory...
Maghis
Jader,Thanks for your response - I was having a tough time getting the problem straight in my mind. The Linq solution is very cool.
markpirvine