Grouping an array - arrays

PLEASE...Help me group the values in this array
I have a an array like this
Arr(0) = 5
Arr(1) = ATC^1
Arr(2) = BTC^2
Arr(3) = ATC^3
Arr(4) = CTC^4
Arr(5) = BTC^5
The end result I want is to change Arr(0) to be 3 which are the number of unique TC's in the group. ATC,BTC and CTC. And I want each of the items for 1,2 and 3 to have the grouped values from the Array.
Arr(0) = 3
Arr(1) = ATC:1,3
Arr(2) = BTC:2,5
Arr(3) = CTC:4
I am trying to do this in MUMPs, so I have no inbuilt sort/group functions.
Even pseudo code will help.

In MUMPS you don't need sort function because array subscripts are being automatically sorted.
So the easiest way is to create another array with sort dimension being first piece of data and value - second piece of data:
for i=1:1:Arr(0) set piece1=$piece(Arr(i),"^",1), piece2=$piece(Arr(i),"^",2), Temp(piece1)=$get(Temp(piece1))_piece2_","
after running that code you will get following array
Temp("ATC")="1,3,"
Temp("BTC")="2,5,"
Temp("CTC")="4,"
Then you traverse that array and build one you need:
set i="",Brr=0 for set i=$o(Temp(i)) quit:i="" set Brr=Brr+1,Brr(Brr)=i_":"_Temp(i)
You will get an array you need:
Brr(1)="ATC:1,3,"
Brr(2)="BTC:2,5,"
Brr(3)="CTC:4,"

Alternate:
Two dimension array:
Temp("ATC",1)=""
Temp("ATC",3)=""
Temp("BTC",2)=""
Temp("BTC",5)=""
Temp("CTC",4)=""
The $o loop can look through the first level for the items in sorted order, then a nested $o to run through the second. Or, just the first if you only want the sorted list. This would save the string logic if you are going to selectively remove elements from the list and just let you set and kill notes in the array.
Sorting logic is uncommon with MUMPS, data is normally loaded/stored into arrays like which keeps them in sorted order.

Related

Find index on array using content

I have create an array of integers.
Dim EnemyLevel() as Integer = {1,2,2,3}
Let's say I wanted to get the position of every item that included '2', that'd be EnemyLevel(1) and EnemyLevel(2), what's the function to do that?
I'm supossed to use Array.IndexOf(EnemyLevel(),2) but how do I store the results?
You run the array in a For Loop. And check if any of the indices contain '2'
Array1 = Array(1,2,2,4)
For i=0 to UBound(Array1)
If Array1(i) = 2 Then
msgbox i
End If
Next

Filling a 3D array with 2D arrays in VBA

I have a set of data where each item has a 2D array of information corresponding to it. I'd like to create a 3D array where the first dimension is the item name and the second and third dimensions are taken up by the info corresponding to the item.
I can read the data for each item into a 2D array, but I can't figure out how to get the 2D array read into the 3D array.
I know the sizes of all the dimensions so I can create an array of fixed size before I begin the reading and writing process.
I'd like to do this by looping only through the names of the items and not looping through every cell of every 2D array.
It is easy to get the 2D arrays read in to an ArrayList but I want to be able to name the items and be able to read these back in to excel and it seems difficult to do with an ArrayList.
The question is: how do I read a 2D selection from excel into a 3D fixed sized array in VBA?
Here is an example of each approach: array of arrays or Dictionary of arrays. The Dictionary approach is considerably easier than the array of arrays if what you want is keyed lookup of values. There might be merits to the array of arrays in other cases.
This is dummy code with no real purpose but to show a couple things: grabbing a single value and an array of values. I am building a 2D array of values by grabbing some Range data which is easy and 2D. From there I build up the arrays of these values and then put them into the relevant data structure. Then I poke at the data structure to get some values out of it.
Array of Arrays approach is shown first (and outputs on the left of the picture).
Sub ArraysOfArrays()
Dim arrA() As Variant
Dim arrB() As Variant
'wire up a 2-D array
arrA = Range("B2:D4").Value
arrB = Range("F2:H4").Value
Dim arrCombo() As Variant
ReDim arrCombo(2, 1) As Variant
'name and give data
arrCombo(0, 0) = "arrA"
arrCombo(1, 0) = arrA
'add more elements
ReDim Preserve arrCombo(2, 2)
arrCombo(0, 1) = "arrB"
arrCombo(1, 1) = arrB
'output a single result
'cell(2,2) of arrA
Range("B6") = arrCombo(1, 0)(2, 2)
Dim str_search As String
str_search = "arrB"
'iterate through and output arrB to cells
Dim i As Integer
For i = LBound(arrCombo, 1) To UBound(arrCombo, 1)
If arrCombo(0, i) = str_search Then
Range("B8").Resize(3, 3).Value = arrCombo(1, i)
End If
Next i
End Sub
Couple key points here:
You can only expand the array using ReDim. ReDim is very particular that you only change the last dimension of the array when used with Preserve. Since I need one of them to track the number of entries, I do that in the second index which is... unnatural. If you know the size in advance, this painful step is skipped.
My final array is a 2xN array where the 2 contains a name and a YxZ array of data.
In order to find a given array in the mix, you have to iterate through them all.
Dictionary of Arrays is far less code and more elegant. Be sure to add the reference Tools->References in the VBA editor to Microsoft Scripting Runtime.
Sub DictionaryOfArrays()
Dim dict As New Scripting.Dictionary
'wire up a 2-D array
arrA = Range("B2:D4").Value
arrB = Range("F2:H4").Value
dict.Add "arrA", arrA
dict.Add "arrB", arrB
'get a single value
Range("F6") = dict("arrB")(2, 2)
'get a array of values
Range("F8").Resize(3, 3) = dict("arrA")
End Sub
Picture of input data and results
Data to copy if you want it (paste in B1)
a b
1 2 3 10 11 12
4 5 6 13 14 15
7 8 9 16 17 18

How to reference an array and write to another array with more than one column per iteration

I am curious if I can copy multiple columns to a new array from an existing array in one iteration of a loop. Suppose we have the following general example:
Array1 contains 10,000 elements in column1, 10,000 elements in column2, and 10,000 elements in column 3, etc.
Let's say that I want a new array generated off that information, only I want only columns 1 and 2 populated. Can I do this by looping only once with a correctly dimensioned target array? For instance:
'Assume TargetArray has already been ReDimmed to the size of Array1 in the code prior
For i=0 to UBound(Array1)
TargetArray(x,1)= Array1(x,1)
TargetArray(x,2)=Array1(x,2)
Next
So can this be done in one step, or do I have to make a loop for each dimension I want to add to the array. Is there any speed savings by doing two operations per loop as stated above (assuming it works).
Thanks for all of your help!
Have you tried just using Range objects? I just made 100 values in columns A and B, and copy them to F and G. Or are you trying to plug values from the first three columns into an equation to give you values for the new two columns?
Sub CopyRange()
Dim Array1 As Range
Dim Array2 As Range
Set Array1 = Range("A1:B100")
Set Array2 = Range("F1:G100")
Array2.Value = Array1.Value
End Sub
Your example should work as what RubberDuck commented.
It is similar in below example which works at my end.
I can't fit it to comments so I have no choice to post it as answer.
Dim TargetArray ' declared as Variant type, not array of variants
ReDim TargetArray(0 To Ubound(Array1, 0), 0 To 1) ' for 2 columns
For i = 0 To Ubound(Array1, 1)
TargetArray(i, 0) = Array1(i, 0)
TargetArray(i, 1) = Array1(i, 1)
Next
Is this close to what you have? If so, then that should work.

Excel VBA: Replace first row by an array

I have a first row with 100 cells and I created an Array of Strings, which represent the new row content.
I would like to replace the content of all the first row with the content of my Array in VBA, how can I do that?
Say your array is called myArray, it's enough to do this:
For j = LBound(myArray) To UBound(myArray)
Sheets("your sheet").Cells(1,j+1).Value = myArray(j)
Next j
The functions LBound() and UBound() are respectively returning the first and the last index of your array.
Please note that when writing Cells(1,j+1) I'm assuming two important things:
1) Your start index starts with 0, so I want to start the insertion of the values from the column 1 (j+1 = 0+1 = 1).
2) You want to override the first row (because the row index is equal to 1).
You might want to customize this, for example creating independent indexes - when I say "independent", I mean "not depending on the lower and the upper bound of your array, nor being hard-coded like I did for the "row 1".
You can read and write between a Range and an Array in one line. It is more efficient than using a loop.
Note: The array must be 2 Dimensional to write to a range.
Public Sub ReadToArray()
' Create dynamic array
Dim StudentMarks() As Variant
' Read values into array from 100 cells in row 1
StudentMarks = Sheets("Sheet1").Range("A1:CV1").Value
' Do something with array
' Write the values back to sheet
Sheets("Sheet1").Range("A1:CV1").Value = StudentMarks
End Sub

how to get the count of items in two dimensional array

I'm trying to get the count of items in one of the dimensions of a 2 dim array.
For example, a simplistic version of my array looks like this:
my_array(0)(1) = "a"
my_array(0)(2) = "b"
my_array(0)(3) = "c"
I'm trying to find out the count of items in my_array(0). But of course you can't do "my_array(0).count", so trying "my_array.count" simply gives me 1. So how do I get the count of the items in the second dimension?
Thanks.
You can use GetLength:
Dim dimLength = my_Array.GetLength(1)
If your looking for the count of every element in your array you might want to consider using the Sum function:
Dim totalcount As Integer = m_array.Sum(Function(x) x.Count)

Resources