Using Large Arrays in VB.NET - vb.net

I want to extract large amounts of data from Excel, manipulate it and put it back. I have found the best way to do this is to extract the data from an Excel Range in to a large array, change the contents on the array and write it back to the Excel Range.
I am now rewriting the application using VB.NET 2008/2010 and wish to take advantage of any new features.
Currently I have to loop through the contents of the array to find elements with certain values; also sorting large arrays is cumbersome. I am looking to use the new features, including LINQ to manipulate the data in my array.
Does anybody have any advice on the easiest ways to filter / query, sort etc. data in a large array. Also what are the reasonable limits to the size of the array?
~Many Thanks

Although you have a multi-pronged question, I've chosen to answer the part about manipulating arrays using LINQ...
Edit - LINQ against 2D array, VB.NET
System.Array (from where all arrays are derived) supports an extension method for .AsQueryable() which means you can process a 2D array with LINQ directly like so:
Option Infer On
Option Strict Off
Public Class DataProcessor
'something like this came from Excel, maybe a Range
Dim arrValues2D(,) As String = { _
{"1", "2", "3"}, _
{"100", "99", "98"}, _
{"2", "3", "4"} _
}
Private Sub FindLargeNumbers()
'LINQ against 2D array elements
Dim query = From v In arrValues2D Where (Int32.Parse(v) > 50 And Int32.Parse(v) < 101) Select CStr(v)
For Each thing As String In query
'do stuff
Console.Write(thing + ",")
Next
End Sub
End Class
Original thoughts
(pretty much deprecated since the above solution)
You could Implement IEnumerable(Of T) and IEnumerator(Of T) in Visual Basic to "flatten" your 2D array (effectively return its values one at a time as if it were a 1D array) and perform operations with the values using LINQ.
Depending on the data type of array elements, in order to write back to them, you might need to wrap each value in something so you can reference the original element instead of a copy of its value.
This is just a general plan to allow you to use LINQ and "new features" against a large efficient 2D array that you already have from Excel.

If you want any performance, you have to stick with extracting the data into arrays, manipulating the arrays, then writing back the data into the range. The performance benefit is significant. I have tested and it is hundreds of times faster.
I do all my array manipulation with custom functions. I do not believe LINQ can compare to my custom functions in speed. What LINQ does bring to the table is flexibility and readability and maintainability. If you design custom array manipulation functions with LINQ principles in mind, then you should be able to take advantage of LINQ without giving up performance. For instance, I had a Median array function. I converted it to a Median extension function that accepted a sequence of doubles then used LINQ over the array to call the Median function.
<Extension()> Public Function Median(ByVal source As IEnumerable(Of Double)) As Double
As in;
Dim m = Aggregate v In arrValues2D Into Median(CDbl(v))

I checked this out of curiosity, and I don't think LINQ is the way to go. I assume that you are reading named ranges into "rectangular" arrays of objects. If that's the case, the bad news is, a rectangular array is non-enumerable and non-queryable, which means you can't execute a LINQ query against it. See the following discussion for details:
querying 2-dimension array with LINQ I stand corrected. Thx to jdk and AMissico for taking the time to explain!

Related

What is the best/fastest method of filling an array with numbers between two values?

I've got a background thread which adds numbers to an array, this call happens often so i'm just curious if there's a faster method of adding the numbers to the array?
I need to add all the numbers between two values (values will be different depending on the situation), example 1 to 4 which would add 1,2,3 & 4.
However, when I make the call, it would be adding much larger arrays similar to 500 to 1000 etc which sometimes takes a little longer depending on how many numbers need to be added.
At the moment i'm using something similiar to this:
Dim ListOfNumbers As New List(Of Integer)
For i = 1 To 100000
If ListOfNumbers.Contains(i) = False Then
ListOfNumbers.Add(i)
End If
Next
Is there any other method that I could use which might be faster?
(Avoiding duplicate values in the array if possible)
I doubt this is driving your program's performance. Moreover, the best option may depend on how you plan to use these numbers, where you may find you actually can noticeably improve performance by using something like IEnumerable throughout your code, rather than an array.
With that in mind, I suggest this option:
int start = 1; int stop = 100000;
var list = Enumerable.Range(start, stop - start).ToArray()
Such that you can easily remove the ToArray() later if desired.
As for the existing code... You control both the List and the loop. Checking .Contains()is not necessary, and probably taking up a significant part of the execution time here. Just remove that check. You can also optimize some by pre-setting the size of the list:
Dim size As Integer = 100000
Dim ListOfNumbers As New List(Of Integer)(size)
For i = 1 To size
ListOfNumbers.Add(i)
Next

How to arrange dates from old to new in vb scripting

I'm developing a macro using extra attachmate. we have a 3rd party tool called CSS from where macro fetches required data. Now I'm trying to arrange dates from old to new.
Firstly I have changed date(10/01/14) to number(140110) and then extracted all values into array. From array is there any Function to sort the numbers or should i compare each value manually in loop?
After comparing the records from array, I have to write this data in different columns of single row.
IF my approach is incorrect then please suggest me correct way.
Thanks,
Yaswanth
Your question talks about a lot of different things. I assume that you want to sort an array of integer. To do that you can use the Sort function.
Dim arr(2) As Integer
arr(0) = 140110
arr(1) = 130110
arr(2) = 150110
Array.Sort(arr)

Total Nos. of items in array variable

I have an array variable (string type). It contains certain no. of items, that I donot know how many they are.
I need to run a loop for that many nos. that the array contains. I tried LBound and UBound loop but it says my array is not a system array.
How can I know how many items my array contains?
Thanks
Furqan
You can use the Length property of the array object.
From MSDN (Array.Length Property):
Gets a 32-bit integer that represents the total number of elements in all the dimensions of the Array.
Read about arrays in VB.NET and the Array class for better understanding of arrays in VB.NET and the .NET framework.
Update:
However, for looping over an array you should simply use a For Each loop (as an array is treated like any other collection in .NET) - this way you will not make any silly mistakes with array bounds and off by ones:
For Each item As arrayItemType in MyArray
' do stuff with item
Next
See the example on this page.
You look at the length:
To get the number of items in the first dimension: arrayName.GetLength(0)
If you need the index, use GetUpperBound(0)
Some helpful examples here.
Like Oded said, you can use the Length-propery of the Array. This would look something like this:
Dim data As String() = {"one", "two", "three", "four"}
For i = 0 To data.Length - 1
Console.WriteLine(data(i))
Next
If you just want to loop all strings in your array, you can use For Each as well:
For Each s As String In data
Console.WriteLine(s)
Next
If the compiler is telling you that your variable is not a system array, then chances are, it's not an array. If it's not an array, you won't be able to get its bounds through any means.
Inspect the variable in the locals window and verify that your variable is of the type that you think it is. It's probably not an array after all.

Visual Basic add to Array dynamically and sort

Still having trouble can you please help?
This needs to be written in Visual Basic
Here is a statement from the Main part of the program...
mylist.ForEach(AddressOf ProcessLink)
What this statement says is the following.... "For each item in the ArrayList "mylist" send item to the sub program "ProcessLink"
Note that ProcessLink is going to receive multiple groups of data from the ArraList "mylist"
ProcessLink then takes each value sent to it and turns it into "P.myName" and P.myValue"
I need ProcessLink to then add these values to an array. And each time it receives a batch of data from the ArrayList "mylist" it will add those values to the same Array. ProcessLink will then sort the array based on "P.Value"
I then need ProcessLink to output the name value pairs in the array and output the result as...
Response.Write("<tr><td>" & P.myName & "</td><td>" & P.myValue & "</td></tr>")
What should the code in ProcessLink look like?
I really reccomend using generic object lists rather than Arrays. You will get all of the functionality you need + 10x more. Sorting, adding, etc are way easier. With generic lists you don't have to worry about declaring the Array size, or any of the difficulties when working with Arrays containing objects. Take a look to the following for more information including the code sample:
.NET Object Collections Using Generics 101:
http://allen-conway-dotnet.blogspot.com/2009/11/net-object-collections-using-generics.html
List(Of T) Class:
http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx

Array in VB .Net

I have an array Newstr(20) When I fill it, I need to know how many of its indexes has been filled ? and find out the values.
I need to know how many of its indexes has been filled ?
Arrays don't keep that information. They only know how many spots you allocated. You have to track how many you assigned yourself. More than that, if you're working with a collection where you don't know how many items there will be, arrays are really the wrong choice in the first place. You should use a List(Of T) instead.
You could populate the array with a known string, then test for that string to see how many elements in your array are filled.
I would - however - suggest using an array list. You can get the number of elements added to the list from the Count property. This is the MSDN entry for Array Lists.
In order to find which of the elements have been filled, you can use a LINQ construction like this:
Dim input() = New String() {"abc", "def", "ghi", "", Nothing}
Dim output = input.Where(Function(i) Not String.IsNullOrEmpty(i)).ToArray
When you run this code, the output array will contain "abc", "def" and "ghi".
You can modify the selector of the Where to suit your preference if you're coding for a different type of array.
For instance the selector for Integer? will be:
input.Where(Function(i) (Not i Is Nothing) Or (i <> 0)).ToArray
Of course, you'll have to be coding in .NET 3.5+ in order to get access to LINQ.