So I have tried different types of visual basic code for this problem that i'm trying to solve but non of them is working :(
I have a jagged array for example {{1 10 20 50 53};{5 15 25 55}}
and I want to convert this information in a binary matrix given the condition that each array in the jagged array corresponds to a row, and the element in it corresponds to a column number. Am I being clear?
The matrix has the same rows as the number of arrays in the jagged array 2, but the columns in the matrix can go for example till 200.
1 0 ... 1 ... 1 ... 1 .. 1..................0
0 0 ... 1 ... 1 ... 1 .... 1 ...............0
My last attempt was this one:
For a = 0 To noRows - 1
For b = 0 To noCols - 1
Do While d < jarray(a).GetUpperBound(0)
If array(a)(d) = b Then
matrix(a, b) = 1
Exit Do
Else
matrix(a, b) = 0
d += 1
End If
Loop
Next
Next
What should I do?
When you make a new array its values are automatically initialised to the default value of the type of variable in the array - for an Integer, that is 0. So you don't need to do the setting to zero unless there is something else that isn't shown in the question.
You have the indexes of the locations which need to be set to 1, so you can do that directly:
Option Infer On
Option Strict On
Module Module1
Sub Main()
'Dim jArray = {New Integer() {1, 10, 20, 50, 53}, New Integer() {5, 15, 25, 55}}
Dim jArray = {New Integer() {1, 3, 4}, New Integer() {2, 5, 6, 7, 9}}
' find the number of columns needed for the resultant array
Dim nCols = jArray.Max(Function(r) r.Max())
' find the number of rows needed for the resultant array
Dim nRows = jArray.GetUpperBound(0) + 1
' the resultant array is automatically initialised to zeros
Dim matrix(nRows, nCols) As Integer
' fill in the ones as specified by the locations in jArray:
For i = 0 To nRows - 1
For j = 0 To jArray(i).GetUpperBound(0)
matrix(i, jArray(i)(j) - 1) = 1
Next
Next
' show the resultant array:
For i = 0 To nRows - 1
For j = 0 To nCols - 1
Console.Write(matrix(i, j) & If(j < nCols - 1, ", ", ""))
Next
Console.WriteLine()
Next
Console.ReadLine()
End Sub
End Module
Outputs:
1, 0, 1, 1, 0, 0, 0, 0, 0
0, 1, 0, 0, 1, 1, 1, 0, 1
Related
I am a VB.Net user. I would like to make an array as per below
Dim QRList() As Integer = {1, 2, 3, 4, 9, 12, 13, 14, 15, 16, 41, 42, 44, 48, 49, 50}
into a series as per below
1 - 4,
9 - 9,
12 - 16,
41 - 42,
44 - 44,
48 - 50,
I have tried the code below. But it doesn't work.
Dim QRList() As Integer = {1, 2, 3, 4, 9, 12, 13, 14, 15, 16, 41, 42, 44, 48, 49, 50}
Dim QRCount As Integer = QRList.Length
Dim startIndex, startN, endN As Integer
For i As Integer = 0 to QRCount - 1
startindex = 0
i = startindex
startN = QRList(i)
Do
If startindex = QRCount - 1 Then
endN = QRList(i)
ElseIf startindex < QRCount - 1 Then
If QRList(i + 1) - QRList(i) + 1 = 1 Then
endN = QRList(i + 1)
ElseIf QRList(i + 1) - QRList(i) + 1 > 1 Then
endN = QRList(i)
Exit For
End If
End If
startindex = i + 1
Console.Writeline(CStr(startN) & " - " & CStr(endN) & vbNewLine)
Loop While startindex < QRCount
Next
Hope anyone can help on this issue, Thanks.
Austin HO
This is a perfect candidate for the Yield statement to return an IEnumerable(Of String). You can pass that resulting IEnumerable(Of String) to String.Join() to obtain the final result.
Here's a quick example:
Sub Main()
Dim QRList() As Integer = {1, 2, 3, 4, 9, 12, 13, 14, 15, 16, 41, 42, 44, 48, 49, 50}
Dim series As String = String.Join("," & vbCrLf, GetSeries(QRList))
Console.WriteLine("Original: " & String.Join(", ", QRList))
Console.WriteLine("Series:")
Console.WriteLine(series)
Console.Write("Press Enter to quit...")
Console.ReadLine()
End Sub
Public Iterator Function GetSeries(ByVal values() As Integer) As IEnumerable(Of String)
Dim startNum, endNum As Integer?
For Each value As Integer In values
If Not startNum.HasValue Then
startNum = value
endNum = value
ElseIf value = (endNum + 1) Then
endNum = value
Else
Yield startNum & " - " & endNum
startNum = value
endNum = value
End If
Next
Yield startNum & " - " & endNum
End Function
Producing the following output:
Original: 1, 2, 3, 4, 9, 12, 13, 14, 15, 16, 41, 42, 44, 48, 49, 50
Series:
1 - 4,
9 - 9,
12 - 16,
41 - 42,
44 - 44,
48 - 50
Press Enter to quit...
Just to make it extra clear what is happening, you can convert the iterator to an array like this:
Dim arrSeries() As String = GetSeries(QRList).ToArray
For i As Integer = 0 To arrSeries.Length - 1
Console.WriteLine(i & ": " & arrSeries(i))
Next
Producing:
0: 1 - 4
1: 9 - 9
2: 12 - 16
3: 41 - 42
4: 44 - 44
5: 48 - 50
And, finally, if you need to work with the actual Integer start and stop values as a set, then simply convert the iterator function to return IEnumerable(Of Tuple(Of Integer, Integer)) instead, and use this Yield statement in the function in both places:
Yield New Tuple(Of Integer, Integer)(startNum, endNum)
Your loop fails at the first comparison: If QRList(i + 1) - QRList(i) + 1 = 1.
Since the condition is not met, the execution continues to the endN = QRList(i) assignment and exits the for loop entirely.
You can simplify this process a bit.
Since you need to generate sequences of contiguous numbers, you just need to determine the starting values - values in the original series that have a distance > 1 - and a variable to store the value of the previous iteration, used to perform the comparison.
Here, I'm using a List of named tuples (List(Of (StartValue As Integer, EndValue As Integer)) to store the values in the series.
You can use a List(Of String), or another type of collection, if that's preferable or named Tuples are not available
Dim QRList As Integer() = { 9, 12, 13, 14, 15, 16, 41, 42, 44, 48, 49, 50, 1, 2, 3, 4}
' Sort the array in case it's not already sorted
Array.Sort(QRList)
Dim maxDistance As Integer = 1
Dim seriesCount As Integer = -1
' Assign starting values that are less than ([Min Value] - [Max Distance])
Dim startValue As Integer = QRList(0) - (maxDistance + 1)
Dim previousValue As Integer = startValue
Dim series As New List(Of (StartValue As Integer, EndValue As Integer))()
For Each value As Integer In QRList
' The distance is less than or equal to the maximum: update the current item
If (value - maxDistance) <= previousValue Then
series(seriesCount) = (startValue, value)
Else
' The distance is > maxDistance: add a new starting item
startValue = value
series.Add((value, value))
seriesCount += 1
End If
previousValue = value
Next
To print the elements in the series:
For Each t In series
Console.WriteLine($"{t.StartValue} - {t.EndValue}")
Next
With maxDistance = 1, the series are:
1 - 4
9 - 9
12 - 16
41 - 42
44 - 44
48 - 50
With maxDistance = 4, the series are:
1 - 4
9 - 16
41 - 50
I want to make heatmap with 1D array(s), this is my plan;
Let assume 4 points of center and each has array,
[center #1, L U] = {0, 1, 2, 5, 10, 7, 4, 2, 1, 0} *L R U D = Left, Right, Up, Down
[center #2, R U] = {0, 1, 1, 4, 12, 7, 5, 3, 2, 1}
[center #3, L D] = {0, 1, 3, 4, 11, 7, 4, 2, 1, 0}
[center #4, R D] = {0, 1, 3, 6, 11, 6, 5, 3, 1, 1}
And when 5th index of heatmap, ([#1]=10, [#2]=12, [#3]=11, [#4]=11) heatmap needs to be like this image.
Heatmap image
Also can predict heatmap is all blue when 1st index ([#1]=0, [#2]=0, [#3]=0, [#4]=0) and only right side has color that almost blue when last index. ([#1]=0, [#2]=1, [#3]=0, [#4]=1)
How can I get 2D matrix from 1D arrays on Matlab? Decreasing values from center can be linear or whatever.
Based on your example you wish to produce always 4 n * n matrices, where the center point of each matrix gets the value in your arrays and all its 4-neighbors get a decreasing value until zero. Did I get it right?
Does this create one of the four matrices you wished to create? If so, just modify the parameters and make four matrices and draw them together
% your matrix size
size = 15
center = (size + 1) / 2
center_value = 5
mat_a = zeros(size,size);
mat_a(center,center) = center_value;
%loop all values until zero
for ii=1:center_value -1
current_value = center_value - ii;
update_mat = mat_a;
% loop over matrix, check if 4-neighbors non-zero
for x =1:size
for y =1:size
if ( mat_a(y,x) == 0 )
has_non_zero_neighbor = false;
% case 1
if ( x < size)
if (mat_a(y,x+1) > 0)
has_non_zero_neighbor = true;
endif
endif
% case 2
if ( y < size)
if (mat_a(y+1,x) > 0)
has_non_zero_neighbor = true;
endif
endif
%case 3
if ( x > 1)
if (mat_a(y,x-1) > 0)
has_non_zero_neighbor = true;
endif
endif
% case 4
if ( y > 1)
if (mat_a(y-1,x) > 0)
has_non_zero_neighbor = true;
endif
endif
%if non-zeros, update matrix item value to current value
if (has_non_zero_neighbor == true)
update_mat(y,x) = current_value;
endif
endif
end
end
mat_a = update_mat;
end
figure(1)
imshow(mat_a./center_value)
I have two arrays
x = [1 1 1 0 2 3 1 1]
y = [1 2 3 4 5 6 7 8]
How to calculate the sum of y's elements for all x(i) = 1 to get the result 1+2+3+7+8 ?
I have used for loop and if then method to calculate the sum value like this
if x(i) = 1 then sum = sum + y(i)
Have other methods to get the results (sum, average, count ...) ?
Thank you.
Since you only want to sum the numbers in y corresponding to 1s in x, but not 0s in x, you can multiply x * y which looks a bit cleaner than the If. Here are a few ways
Dim x = {1, 1, 1, 0, 0, 0, 1, 1}
Dim y = {1, 2, 3, 4, 5, 6, 7, 8}
' using a for loop
Dim sum1 As Integer = 0
For i = 0 To x.Length - 1
sum1 += If(x(i) = 1, 1, 0) * y(i)
Next
Console.WriteLine(sum1)
' using LINQ #1
Dim sum2 As Integer = x.Select(Function(i, index) If(i = 1, 1, 0) * y(index)).Sum()
Console.WriteLine(sum2)
' using LINQ #2
Dim sum3 As Integer = x.Zip(y, Function(x1, y1) If(x1 = 1, 1, 0) * y1).Sum()
Console.WriteLine(sum3)
' using LINQ #3
Dim sum4 As Integer = Enumerable.Range(0, x.Length).Sum(Function(i) If(x(i) = 1, 1, 0) * y(i))
Console.WriteLine(sum4)
Console.ReadLine()
The For is very clear so I don't know why you wouldn't use it, but you can use LINQ for this as well:
Sub Main
Dim x = {1, 1, 1, 0, 2, 3, 1, 1}
Dim y = {1, 2, 3, 4, 5, 6, 7, 8}
Dim sum = y.Where(Function(v, i) x(i) = 1).Sum()
Console.WriteLine("Sum is {0}", sum)
End Sub
Prints
Sum is 21
I have an array containing 5 integers. For example:
myArray = Array(3, 5, 2, 9, 3)
I want to write a loop that loops through the elements of the array, and on each iteration returns the product of the current element and all elements to the right of it.
In the example above:
3 * 5 * 2 * 9 * 3
5 * 2 * 9 * 3
2 * 9 * 3
9 * 3
3
My non-VBA thinking was along the lines of:
for i in myArray
product(myArray[i:])
But I don't know how to write this in VBA, especially since it doesn't support array subsetting. Any help is welcome.
You need two loops:
Sub foo()
Dim myArray
myArray = Array(3, 5, 2, 9, 3)
Dim i&, j&
Dim output As Double
For i = LBound(myArray) To UBound(myArray)
output = 1
For j = i To UBound(myArray)
output = output * myArray(j)
Next j
Debug.Print output
Next i
End Sub
I have a large array of single digit integers (0 - 9) and I would like to turn a subset of the values into a single integer value. For example:
Array(0) = 4
Array(1) = 2
Array(2) = 1
Array(3) = 6
Array(4) = 7
Array(5) = 4
Array(6) = 8
Array(7) = 2
Array(8) = 9
Array(9) = 0
I would like the then make a number using (for example) array indexes 4,5 and 6;
NewInt = 748
The only way i can see of doing this is making a string and then an integer (as in CInt(Cstr(Array(5) & Array(6)...)) but this seems needlessly slow. The whole point of what I'm doing is about speeding things up.
Any suggestions?
Take a look at this.
Dim nums() As Integer = {4, 2, 1, 6, 7, 4, 8, 2, 9, 0}
Dim ans As Long = 0L
Dim useNums() As Integer = {4, 5, 6}
For Each idx As Integer In useNums
ans = (ans * 10L) + nums(idx)
Next