How to sort array of strings by their lengths - vb.net

I have an array of strings such as "blue", "green", "red" and I wish to sort them so the longest string comes first and the shortest last.
Currently I am creating another array with the lengths of each string in the array in the same index positions and using this array as the key array to sort by as can be seen below, but I think this could be optimised into one line perhaps?
Dim colours() As string = {"blue", "green", "red"}
Dim colourslength() As Integer
For i As Integer = 0 To colours.Length - 1
colourslength(i) = colours(i).Length
Next
Array.Sort(colourslength, colours)
Array.Reverse(colours)
Edit: just realised I defined colours as a list in the example code, it's an array in my actual code.

Another Linq solution (warning, converted from C#)
Dim Sorted = From p In colours Order By p.Length Descending Select p

To my opinion this is the shortes way. Use linq.
Dim strs = New String() {"", "333", "22", "4444", "55555", "1"}
Dim sorted = strs.OrderBy(Function(x) x.Length).ThenBy(Function(x) x).ToArray()
Edit
If you want a reverse order just get rid of extra method call an do the sortin in a reverse order
Dim strs = New String() {"", "333", "22", "4444", "55555", "1"}
Dim sorted = strs.OrderByDescending(Function(x) x.Length).ThenByDescending(Function(x) x).ToArray
Cheers.

Dim colours = {"blue", "green", "red"}
Dim coloursSortedByLength = colours.OrderByDescending(Function(c) c.Length)
Output sequence is: green, blue, red.

The best simple way to do it, is to compare every string with all other strings in your list:
in Java:
for(int i=0; i<list.length-1; i++){
for(int j=i+1; j<list.length; j++){
if(list[i].length() < list[j].length()){
tmp = list[i];
list[i] = list[j];
list[j] = tmp;
}
}
}

Related

Directcast or ctype on a any string in VB.Net

I would like to use something like directcast, or ctype but this time for a string. Unfortunately, I don't know how to proceed.
Public bttkey1color, bttkey2color, bttkey3color, bttkey4color, bttkey5color,
bttkey6color, bttkey7color as string
Dim myColor As String() = IO.File.ReadAllLines(My.Application.Info.DirectoryPath + ("\Color.txt"))
how can i reduce this code? I don't need to write this dozens of times.
bttkey1color = myColor(1)
bttkey2color = myColor(2)
bttkey3color = myColor(3)
bttkey4color = myColor(4)
bttkey5color = myColor(5)
bttkey6color = myColor(6)
bttkey7color = myColor(7)
You can use the Color.FromName(String) Method.
To reduce the code, use an array of Color for the result, instead of individual variables.
' Test
Dim colorNames As String() = {"Lime", "Black", "Red"}
Dim colors As Color() = colorNames.
Select(Function(s) Color.FromName(s)).ToArray()
For Each c In colors
Console.WriteLine(c)
Next
Prints
Color [Lime]
Color [Black]
Color [Red]
Or, if you are not comfortable with LINQ, here a solution using For-loops
Dim colorNames As String() = {"Lime", "Black", "Red"}
Dim colors(colorNames.Length - 1) As Color
For i = 0 To colorNames.Length - 1
colors(i) = Color.FromName(colorNames(i))
Next
For Each c In colors
Console.WriteLine(c)
Next
See also
Arrays in Visual Basic
Collections (Visual Basic) (as an alternative to arrays)

Substring Method in VB.Net

I have Textboxes Lines:
{ LstScan = 1,100, DrwR2 = 0000000043 }
{ LstScan = 2,200, DrwR2 = 0000000041 }
{ LstScan = 3,300, DrwR2 = 0000000037 }
I should display:
1,100
2,200
3,300
this is a code that I can't bring to a working stage.
Dim data As String = TextBox1.Lines(0)
' Part 1: get the index of a separator with IndexOf.
Dim separator As String = "{ LstScan ="
Dim separatorIndex = data.IndexOf(separator)
' Part 2: see if separator exists.
' ... Get the following part with Substring.
If separatorIndex >= 0 Then
Dim value As String = data.Substring(separatorIndex + separator.Length)
TextBox2.AppendText(vbCrLf & value)
End If
Display as follows:
1,100, DrwR2 = 0000000043 }
This should work:
Function ParseLine(input As String) As String
Const startKey As String = "LstScan = "
Const stopKey As String = ", "
Dim startIndex As String = input.IndexOf(startKey)
Dim length As String = input.IndexOf(stopKey) - startIndex
Return input.SubString(startIndex, length)
End Function
TextBox2.Text = String.Join(vbCrLf, TextBox1.Lines.Select(AddressOf ParseLine))
If I wanted, I could turn that entire thing into a single (messy) line... but this is more readable. If I'm not confident every line in the textbox will match that format, I can also insert a Where() just before the Select().
Your problem is you're using the version of substring that takes from the start index to the end of the string:
"hello world".Substring(3) 'take from 4th character to end of string
lo world
Use the version of substring that takes another number for the length to cut:
"hello world".Substring(3, 5) 'take 5 chars starting from 4th char
lo wo
If your string will vary in length that needs extracting you'll have to run another search (for example, searching for the first occurrence of , after the start character, and subtracting the start index from the newly found index)
Actually, I'd probably use Split for this, because it's clean and easy to read:
Dim data As String = TextBox1.Lines(0)
Dim arr = data.Split()
Dim thing = arr(3)
thing now contains 1,100, and you can use TrimEnd(","c) to remove the final comma
thing = thing.TrimEnd(","c)
You can reduce it to a one-liner:
TextBox1.Lines(0).Split()(3).TrimEnd(","c)

VB.net If or statement

I have a textbox that people enter a number or a range, eg 12-15, and a random number is generated. Currently if the second number is less than the first I can get it to work how I want but not if only a single number is listed.
rnum1 should equal rnum2 if there isn't a words(1) or if it's less than words(0). (I do have it done if it's less.)
Dim words As String() = TextBox2.Text.Split("-")
Dim rnum1 As String = words(0)
Dim rnum2 As String = words(1)
Dim RandomClass As New Random()
Dim RandomNumber As Integer
If rnum2 < rnum1 Then
rnum2 = rnum1
End If
RandomNumber = RandomClass.Next(rnum1, rnum2)
Change this line
Dim rnum2 As String = words(1)
to
Dim rnum2 As String = IF(words.Length = 2, words(1), rnum1)
It checks whether there're 2 elements in words array. If it is - it uses second element of array, otherwise it reassigns the first.
Come to think of it, this can be achieved even by this:
Dim rnum2 As String = words(words.Length - 1)
If there're 2 elements in the array - it will assign words(1), otherwise words(0)

Retrieving re-occurring characters from a string

I need to get a certain character from a long string line, that occurs more than once. This is what the string looks like:
<Press T><Press Left><Press A><Press C><Press P><Press U><Press G><Press P><Press NumPad7><Press NumPad7><Press A>
I need to loop through each set of <>'s and get the info that is after each occurrence of the word Press. So in this case I would need the info T, Left, A, C, P, etc
I think this pure String-method approach is the most efficient, but it requires the format to be strict:
Dim text = "<Press T><Press Left><Press A><Press C><Press P><Press U><Press G><Press P><Press NumPad7><Press NumPad7><Press A>"
Dim allKeys As New List(Of String)
Dim pattern = "Press "
Dim index = text.IndexOf(pattern)
While index >= 0
index += pattern.Length
Dim endIndex = text.IndexOf(">", index)
If endIndex >= 0 Then
Dim nextKey = text.Substring(index, endIndex - index)
allKeys.Add(nextKey)
index = text.IndexOf(pattern, endIndex + 1)
Else
Exit While
End If
End While
Console.Write(String.Join(", ", allKeys))
Output: T, Left, A, C, P, U, G, P, NumPad7, NumPad7, A
Here is the Regex that returns all matches, you find the "key" that was pressed in the second group:
pattern = "<Press ([^>]+)>"
Dim regex = New Regex( pattern, RegexOptions.Compiled And RegexOptions.IgnoreCase)
For Each match As Match In regex.Matches(text)
Console.WriteLine(match.Groups(1))
Next
Assuming it's the same format all the time you can do this in one line. Regex would be better if there's a chance the format would be different (e.g. random number of whitespaces etc..)
Dim myString As String = "<Press T><Press Left><Press A><Press C><Press P><Press U><Press G><Press P><Press NumPad7><Press NumPad7><Press A>"
Dim character As String() = myString.Split(New String() {"<Press ", ">"}, StringSplitOptions.RemoveEmptyEntries)
RegEx, short for regular expressions, is an easy way to parse strings. This site Provides good information on using RegEx in .NET. It's how I learned. The site also provides good info on RegEx in general if you are not familiar.
Edit: RegEx expressions can be complicated to create. A great tool to help you out with that is Expresso. It'll help you create and test very complicated expressions with a minimal of fuss.
Dim s As String = "<Press T><Press Left><Press A><Press C><Press P><Press U><Press G><Press P><Press NumPad7><Press NumPad7><Press A>"
Dim ss() As String = s.Replace("<Press ", "").Split(">"c)
For i as integer = 0 to ss.count - 2
Debug.Print(ss(i))
Next
Output:
T
Left
A
C
P
U
G
P
NumPad7
NumPad7
A
Note that the array ss is one longer than the number of key presses due to the final ">" being treated as another separator by .split, you could always remove the final ">"

Join two items from an array using VB

I am creating an array as follows
Dim strFriends(0 to 6) As String
strFriends(0) = "Bianca"
strFriends(1) = "Jeana"
strFriends(2) = "Sam"
strFriends(3) = "Jenna"
strFriends(4) = "Erin"
strFriends(5) = "Carolyn"
strFriends(6) = "Kate"
Dim myFriends As String
myFriends = Join(strFriends, ", ")
MsgBox myFriends
This will produce the following string: "Bianca, Jeana, Sam, Jenna, Erin, Carolyn, Kate"
But I need to retrieve specific items in array and display them as list, something like this:
e.g: If I want to select from strFriends, Kate ,Sam and Bianca
It should list like
Kate
Sam
Bianca
How to perform the task. I am really new to VB so I am confused with this simple task. Can anyone help.
Thank you
Dim strFriends(0 To 6) As String
strFriends(0) = "Bianca"
strFriends(1) = "Jeana"
strFriends(2) = "Sam"
strFriends(3) = "Jenna"
strFriends(4) = "Erin"
strFriends(5) = "Carolyn"
strFriends(6) = "Kate"
Dim objOutput As Text.StringBuilder = New Text.StringBuilder()
For Each strFriend As String In strFriends
Select Case strFriend
Case "Kate", "Sam", "Bianca"
objOutput.AppendLine(strFriend)
End Select
Next
MessageBox.Show(objOutput.ToString())
Or
For Each strFriend As String In strFriends
If MyLogicToDetermineSelected(strFriend) Then
objOutput.AppendLine(strFriend)
End If
Next
It's not clear why you need to pick items from the original array when you already know which items you want, so I won't answer that part of the question. As for displaying each item on it's own line, you can do this with String.Join:
Dim chosenFriends As String() = {"Kate", "Sam", "Bianca"}
Dim output As String = String.Join(Environment.NewLine, chosenFriends)