Find the length of a word in an array - Visual Basic - vb.net

I have a richtextbox and I converted the words to an array, then I have code that will take the length and the output it... only problem is I don't know how to loop through all the different values of the array to check the length of each individual part of the array.
(I have this set on TextChanged)
Dim len1, len2, len3, len4, len5, len6, len7, len8, len9, len10, len11, len12, len13, len14, len15 As Integer
Dim input As String
Dim words As String()
Dim length As Integer
input = RichTextBox1.Text
words = input.Split(New String() {" "}, StringSplitOptions.RemoveEmptyEntries)
For Each w In words
length = Len(w)
Select Case length
Case 1
len1 = len1 + 1
Case 2
len2 = len2 + 1
Case 3
len3 = len3 + 1
Case 4
len4 = len4 + 1
Case 5
len5 = len5 + 1
Case 6
len6 = len6 + 1
Case 7
len7 = len7 + 1
Case 8
len8 = len8 + 1
Case 9
len9 = len9 + 1
Case 10
len10 = len10 + 1
Case 11
len11 = len11 + 1
Case 12
len12 = len12 + 1
Case 13
len13 = len13 + 1
Case 14
len14 = len14 + 1
Case 15
len15 = len15 + 1
End Select
Next
letcount.onelet.Text = Val(len1)
letcount.twolet.Text = Val(len2)
letcount.threelet.Text = Val(len3)
letcount.fourlet.Text = Val(len4)
letcount.fivelet.Text = Val(len5)
letcount.sixlet.Text = Val(len6)
letcount.sevenlet.Text = Val(len7)
letcount.eightlet.Text = Val(len8)
letcount.ninelet.Text = Val(len9)
letcount.tenlet.Text = Val(len10)
letcount.elevenlet.Text = Val(len11)
letcount.twelevelet.Text = Val(len12)
letcount.thirteenlet.Text = Val(len13)
letcount.fourteenlet.Text = Val(len14)
letcount.fifteenlet.Text = Val(len15)

bendataclear showed you how to use a For Next loop. If you can use LINQ, you can use the following code:
Sub Main
Dim words As String() = {"One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten" }
Dim lengthsOnly = words.Select(Function(w) w.Length).ToArray()
Dim wordsAndLengths = words.Select(Function(w) New With { .Word = w, .Length = w.Length }).ToArray()
End Sub
The first Select gets only the word lengths, the second returns an array with each word and it's length.

David,
Some clarification for you:
w is a string. The compiler determines the type at design time. See this S.O. thread
What does VB.Net For Each Loop look at to Infer the Type
Dim words() As String = {"0", "1", "2"}
For Each w In words
System.Windows.Forms.MessageBox.Show(w)
Next
The type is inferred by the compiler by looking at the elements in the IEnumerable collection (array, list, etc.) The intellisense even knows it's a string at design time, even when w looks like it is defined as a generic. Try it yourself...
BUT. You can of course add the type explicitly
Dim words() As String = {"0", "1", "2"}
For Each w As String In words
System.Windows.Forms.MessageBox.Show(w)
Next
The string array example doesn't really demonstrate the convenience of the shorthand. See below
Dim dictionaryOfDictionaries As New Dictionary(Of String, Dictionary(Of String, String))
For Each d As KeyValuePair(Of String, Dictionary(Of String, String)) In dictionaryOfDictionaries
' do something with each dictionary d
Next
' is identical to
For Each d In dictionaryOfDictionaries
' do something with each dictionary d
Next

You can ignore double spaces and enters because they are considered empty:
'HOW CAN I EXCLUDE DOUBLE SPACES
'AND INCLUDE IF SOMEBODY PRESSES ENTER?
words = input.Split(New String() {" "}, StringSplitOptions.RemoveEmptyEntries)

You could use another array?
Dim arr(14) as integer
Dim input As String
Dim words As String()
Dim length As Integer
input = RichTextBox1.Text
words = Split(input, " ")
For Each w in words
Dim l as Integer = Math.Min(Len(w) - 1,14)
arr(l) = arr(l) + 1
Next
Edit
In answer to questions in the comment:
w is a variable, and it is declared in the shortcut code For Each w in words
The shortcut declares a variable w then populates it with each member of the array words and runs the code between the For and next.
A longer way to do this without the shortcut would be something like:
Dim i as Integer
For i = 0 to words.GetUpperBound(0) -1
Dim w as string
w = words(i)
i = i + 1
'Rest of code
Next i
The next part Dim l as Integer = Math.Min(Len(w) - 1,14) sets l to the length of the word up to 14, as if we have a word longer than 15 letters it won't fit in the array.
Another way to do it would be:
Dim l as Integer
l = Len(w) - 1
If l > 14 then
l = 14
End If
arr(l) = arr(l) + 1

Related

Splitting string every 100 characters not working

I am having a problem where I just can't seem to get it to split or even display the message. The message variable is predefined in another part of my code and I have debugged to make sure that the value comes through. I am trying to get it so that every 100 characters it goes onto a new line and with every message it also goes onto a new line.
y = y - 13
messagearray.AddRange(Message.Split(ChrW(100)))
Dim k = messagearray.Count - 1
Dim messagefin As String
messagefin = ""
While k > -1
messagefin = messagefin + vbCrLf + messagearray(k)
k = k - 1
End While
k = 0
Label1.Text = Label1.Text & vbCrLf & messagefin
Label1.Location = New Point(5, 398 + y)
You can use regular expression. It will create the array of strings where every string contains 100 characters. If the amount of remained characters is less than 100, it will match all of them.
Dim input = New String("A", 310)
Dim mc = Regex.Matches(input, ".{1,100}")
For Each m As Match In mc
'// Do something
MsgBox(m.Value)
Next
You can use LINQ to do that.
When you do a Select you can get the index of the item by including a second parameter. Then group the characters by that index divided by the line length so, the first character has index 0, and 0 \ 100 = 0, all the way up to the hundredth char which has index 99: 99 \ 100 = 0. The next hundred chars have 100 \ 100 = 1 to 199 \ 100 = 1, and so on (\ is the integer division operator in VB.NET).
Dim message = New String("A"c, 100)
message &= New String("B"c, 100)
message &= New String("C"c, 99)
Dim lineLength = 100
Dim q = message.Select(Function(c, i) New With {.Char = c, .Idx = i}).
GroupBy(Function(a) a.Idx \ lineLength).
Select(Function(b) String.Join("", b.Select(Function(d) d.Char)))
TextBox1.AppendText(vbCrLf & String.Join(vbCrLf, q))
It is easy to see how to change the line length because it is in a variable with a meaningful name, for example I set it to 50 to get the output
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
You can use String.SubString to do that. Like this
Dim Message As String = "your message here"
Dim MessageList As New List (Of String)
For i As Integer = 0 To Message.Length Step 100
If (Message.Length < i + 100) Then
MessageList.Add(Message.SubString (i, Message.Length - i)
Exit For
Else
MessageList.Add(Message.SubString (i, 100))
End If
Next
Dim k = MessageList.Count - 1
...
Here is what your code produced with a bit of clean up. I ignored the new position of the label.
Private Sub OpCode()
Dim messagearray As New List(Of String) 'I guessed that messagearray was a List(Of T)
messagearray.AddRange(Message.Split(ChrW(100))) 'ChrW(100) is lowercase d
Dim k = messagearray.Count - 1
Dim messagefin As String
messagefin = ""
While k > -1
messagefin = messagefin + vbCrLf + messagearray(k)
k = k - 1
End While
k = 0 'Why reset k? It falls out of scope at End Sub
Label1.Text = Label1.Text & vbCrLf & messagefin
End Sub
I am not sure why you think that splitting a string by lowercase d would have anything to do with getting 100 characters. As you can see the code reversed the order of the list items. It also added a blank line between the existing text in the label (In this case Label1) and the new text.
To accomplish your goal, I first created a List(Of String) to store the chunks. The For loop starts at the beginning of the input string and keeps going to the end increasing by 10 on each iteration.
To avoid an index out of range which would happen at the end. Say, we only had 6 characters left from start index. If we tried to retrieve 10 characters we would have an index out of range.
At the end we join the elements of the string with the separated of new line.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
BreakInto10CharacterChunks("The quick brown fox jumped over the lazy dogs.")
End Sub
Private Sub BreakInto10CharacterChunks(input As String)
Dim output As New List(Of String)
Dim chunk As String
For StartIndex = 0 To input.Length Step 10
If StartIndex + 10 > input.Length Then
chunk = input.Substring(StartIndex, input.Length - StartIndex)
Else
chunk = input.Substring(StartIndex, 10)
End If
output.Add(chunk)
Next
Label1.Text &= vbCrLf & String.Join(vbCrLf, output)
End Sub
Be sure to look up String.SubString and String.Join to fully understand how these methods work.
https://learn.microsoft.com/en-us/dotnet/api/system.string.substring?view=netframework-4.8
and https://learn.microsoft.com/en-us/dotnet/api/system.string.join?view=netframework-4.8

Count a specific string in a multiline textbox (VB.Net)

I very much want to count the values in a multiline textbox each time each value appears in descending order> in ascending order. I tried a lot but nothing works as it should. (VB.Net)
Textbox1.Lines
2
3
2
2
4
7
7
7
28
28
Expected Output: Textbox2.Lines
2 = Count = 3
7 = Count = 3
28 = Count = 2
3 = Count = 1
4 = Count = 1
What i try and dind't worked.
#1
Public Function CountCharacter(ByVal value As String, ByVal ch As Char) As Integer
Dim cnt As Integer = 0
For Each c As Char In value
If c = ch Then
cnt += 1
End If
Next
Return cnt
End Function
#2
Dim a As String = "this is test"
Dim pattern As String = "t"
Dim ex As New System.Text.RegularExpressions.Regex(pattern)
Dim m As System.Text.RegularExpressions.MatchCollection
m = ex.Matches(a)
MsgBox(m.Count.ToString())
#3
Public Shared Function StrCounter(str As String, CountStr As String) As Integer
Dim Ctr As Integer = 0
Dim Ptr As Integer = 1
While InStr(Ptr, str, CountStr) > 0
Ptr = InStr(Ptr, str, CountStr) + Len(CountStr)
Ctr += 1
End While
Return Ctr
End Function
You need to remember which strings have already appeared and then count them. To do that, you can use a dictionary.
Dim dict_strCount As Dictionary(Of String, Integer) = New Dictionary(Of String, Integer)()
' Run over each line in the input
For Each line As String In tb_yourTextBox.Text.Lines
' Check if we have already counted the string in this line
If dict_strCount.ContainsKey(line) Then
dict_strCount(line) += 1 ' if so, increment that count
Else
dict_strCount.Add(line, 1) ' if not, add it to the dictionary (with count of 1)
End If
Next
tb_yourOutputTextBox.Text = String.Empty ' clear the output
' run over all the elements in the dictionary in ascending order by value
' and output to the output textbox
For Each kvp As KeyValuePair(Of String, Integer) In dict_strCount.OrderBy(Function(x) x.Value)
tb_yourOutputTextBox.Text += kvp.Key & ": " & kvp.Value.ToString() & vbNewLine
Next
You may test it here

Split text lines into words and decide which one is correct based on voting

The following code splits each lines into words and store the first words in each line into array list and the second words into another array list and so on. Then it selects the most frequent word from each list as correct word.
Module Module1
Sub Main()
Dim correctLine As String = ""
Dim line1 As String = "Canda has more than ones official language"
Dim line2 As String = "Canada has more than one oficial languages"
Dim line3 As String = "Canada has nore than one official lnguage"
Dim line4 As String = "Canada has nore than one offical language"
Dim wordsOfLine1() As String = line1.Split(" ")
Dim wordsOfLine2() As String = line2.Split(" ")
Dim wordsOfLine3() As String = line3.Split(" ")
Dim wordsOfLine4() As String = line4.Split(" ")
For i As Integer = 0 To wordsOfLine1.Length - 1
Dim wordAllLinesTemp As New List(Of String)(New String() {wordsOfLine1(i), wordsOfLine2(i), wordsOfLine3(i), wordsOfLine4(i)})
Dim counts = From n In wordAllLinesTemp
Group n By n Into Group
Order By Group.Count() Descending
Select Group.First
correctLine = correctLine & counts.First & " "
Next
correctLine = correctLine.Remove(correctLine.Length - 1)
Console.WriteLine(correctLine)
Console.ReadKey()
End Sub
End Module
My Question: How can I make it works with lines of different number of words. I mean that the length of each lines here is 7 words and the for loop works with this length (length-1). Suppose that line 3 contains 5 words.
EDIT: Accidentally had correctIndex where shortest should have been.
From what I can tell you are trying to see which line is the closest to the correctLine.
You can get the levenshtein distance using the following code:
Public Function LevDist(ByVal s As String,
ByVal t As String) As Integer
Dim n As Integer = s.Length
Dim m As Integer = t.Length
Dim d(n + 1, m + 1) As Integer
If n = 0 Then
Return m
End If
If m = 0 Then
Return n
End If
Dim i As Integer
Dim j As Integer
For i = 0 To n
d(i, 0) = i
Next
For j = 0 To m
d(0, j) = j
Next
For i = 1 To n
For j = 1 To m
Dim cost As Integer
If t(j - 1) = s(i - 1) Then
cost = 0
Else
cost = 1
End If
d(i, j) = Math.Min(Math.Min(d(i - 1, j) + 1, d(i, j - 1) + 1),
d(i - 1, j - 1) + cost)
Next
Next
Return d(n, m)
End Function
And then, this would be used to figure out which line is closest:
Dim correctLine As String = ""
Dim line1 As String = "Canda has more than ones official language"
Dim line2 As String = "Canada has more than one oficial languages"
Dim line3 As String = "Canada has nore than one official lnguage"
Dim line4 As String = "Canada has nore than one offical language"
Dim lineArray As new ArrayList
Dim countArray As new ArrayList
lineArray.Add(line1)
lineArray.Add(line2)
lineArray.Add(line3)
lineArray.Add(line4)
For i = 0 To lineArray.Count - 1
countArray.Add(LevDist(lineArray(i), correctLine))
Next
Dim shortest As Integer = Integer.MaxValue
Dim correctIndex As Integer = 0
For i = 0 To countArray.Count - 1
If countArray(i) <= shortest Then
correctIndex = i
shortest = countArray(i)
End If
Next
Console.WriteLine(lineArray(correctIndex))

Finding the position of a character in a string

I need to add a code (123456) into a line of text in a file.
\\ESSEX [D]\\\\\\Tina Richardes\\\\\\\\\\\\\\\\\\\\\\\
The code needs to be entered after the 3rd "\" so it would look something like this.
\\ESSEX [D]\123456\\\\\Tina Richardes\\\\\\\\\\\\\\\\\\\\\\\
The text is always located on line 124 of the file.
If the [D] is always there a short and easy way would be to do:
Dim MyString As String = "\\ESSEX [D]\\\\\\Tina Richardes\\\\\\\\\\\\\\\\\\\\\\\"
MyString = MyString.Insert(MyString.IndexOf("[D]") + 3, "123456")
Otherwise you could do:
Dim MyString As String = "\\ESSEX [D]\\\\\\Tina Richardes\\\\\\\\\\\\\\\\\\\\\\\"
Dim d As Integer = 0
For Each i As Match In Regex.Matches(MyString, "\\")
If d = 2 Then
MsgBox(MyString.Insert(i.Index + 1, "132456"))
End If
d = d + 1
Next
You can use File.ReadAllLines and File.WriteAllLines and string methods:
Dim lines = File.ReadAllLines(path)
If lines.Length < 124 Then Return
Dim line = lines(123)
Dim tokens = line.Split(New String() {"\"}, StringSplitOptions.None)
If tokens.Length < 4 Then Return
tokens(3) = "123456"
lines(123) = String.Join("\", tokens)
File.WriteAllLines(path, lines)
I would just loop through the string, counting the occurrences of the backslash and then exiting when you have found the third occurrence.
You would need to keep count of the index and then use this with the String.Insert method to insert the "123456" code:
Dim s As String = "\\ESSEX [D]\\\\\\Tina Richardes\\\\\\\\\\\\\\\\\\\\\\\"
Dim count As Integer = 0
Dim index As Integer = 0
For Each c In s
If c = "\" Then count += 1
index += 1
If count = 3 Then Exit For
Next
s = s.Insert(index, "123456")
Output:
\\ESSEX [D]\123456\\\\\Tina Richardes\\\\\\\\\\\\\\\\\\\\\\\

I have three variables declared as strings, is there a way to randomly choose one? [duplicate]

This question already has answers here:
How can I randomly select one of three strings?
(2 answers)
Closed 8 years ago.
I have three strings, sUpperCase, sLowerCase and sNumbers. Each have either lower characters, upper characters or numbers. I need to know how to randomly choose one of these strings. I have thought maybe by assigning them a number but I am not sure how do to this without overriding the text inside of them. Maybe even an array but I'm not sure how to do this either. Can anybody help please?
Dim sLowerCase As String = "qwertyuiopasdfghjklzxcvbnm"
Dim sUpperCase As String = "MNBVCXZLKJHGFDSAPOIUYTREWQ"
Dim sNumbers As String = "1234567890"
ANSWER:
Function GeneratePassword() As String
'
' Declare two strings as the characters which the password can be created from
Dim sLowerCase As String = "qwertyuiopasdfghjklzxcvbnm"
Dim sUpperCase As String = "MNBVCXZLKJHGFDSAPOIUYTREWQ"
Dim sNumbers As String = "1234567890"
' Create a new random.
' Random is something which gets a random set of characters from a string.
Dim random As New Random
'
' Create sPassword as a new stringbuilder
' A stringbuilder is simply a class which builds a string from multiple characters
Dim sPassword As New StringBuilder
' Not random enough
'For i As Integer = 1 To 4
' Dim idxUpper As Integer = random.Next(0, sUpperCase.Length - 1)
' sPassword.Append(sUpperCase.Substring(idxUpper, 1))
' Dim idxNumber As Integer = random.Next(0, sNumbers.Length - 1)
' sPassword.Append(sNumbers.Substring(idxNumber, 1))
' Dim idxLower As Integer = random.Next(0, sLowerCase.Length - 1)
' sPassword.Append(sLowerCase.Substring(idxLower, 1))
'Next
' Random select Upper, lower or numeric
' Check for a max number of this(three if's to check for which one it was, might need or in if)
' If yes randomly select another one
' If no get random char from that type
' Add to password
' Is the password complete?
' If yes return password, if not repeat
Dim iCountUpper As Integer = 0
Dim iCountLower As Integer = 0
Dim iCountNumber As Integer = 0
Do Until sPassword.Length = 10
'Needed help for this bit
Dim x = New Random(Now.GetHashCode)
Dim y = {"sLowerCase", "sUpperCase", "sNumbers"}
Dim z = y(x.Next(0, y.Length))
If z.Contains("sLowerCase") And iCountUpper < 4 Then
Dim idxUpper As Integer = random.Next(0, sUpperCase.Length - 1)
sPassword.Append(sUpperCase.Substring(idxUpper, 1))
iCountUpper = iCountUpper + 1
ElseIf z.Contains("sUpperCase") And iCountLower < 4 Then
Dim idxLower As Integer = random.Next(0, sLowerCase.Length - 1)
sPassword.Append(sLowerCase.Substring(idxLower, 1))
iCountLower = iCountLower + 1
ElseIf z.Contains("sNumbers") And iCountNumber < 2 Then
Dim idxNumber As Integer = random.Next(0, sNumbers.Length - 1)
sPassword.Append(sNumbers.Substring(idxNumber, 1))
iCountNumber = iCountNumber + 1
Else
End If
Loop
'
' Return the password as a string
Return sPassword.ToString
End Function
You could do something like this:
Dim sLowerCase As String = "qwertyuiopasdfghjklzxcvbnm"
Dim sUpperCase As String = "MNBVCXZLKJHGFDSAPOIUYTREWQ"
Dim sNumbers As String = "1234567890"
Dim x = New Random(Now.GetHashCode)
Dim y = {sLowerCase, sUpperCase, sNumbers}
Dim z = y(x.Next(0, y.Length))
Debug.Print(z)
Dim strings = {"qwertyuiopasdfghjklzxcvbnm", "MNBVCXZLKJHGFDSAPOIUYTREWQ", "1234567890"}
Dim selected As String
Dim Generator As System.Random = New System.Random()
selected = strings(Generator.Next(0, strings.GetUpperBound(0)))
Create an array with your strings:
Dim array As String() = New String() {sLowerCase, sUpperCase, sNumbers}
Use Random class to generate random number between 0 and the array lenght:
Dim random As Random = New Random(DateTime.Now.Ticks)
Dim randomChoose As String = array(random.Next(0, array.Length - 1))
Select a random char:
Dim ch As Char = randomChoose(random.Next(0, randomChoose.Length - 1))