Weird results when splitting strings in VB.NET - vb.net

I was getting weird results when doing multiple splits on a string, so I decided to make a simple test to figure out what was going on
testString "1234567891011121314151617181920"
If I wanted to get whats between 10 to 20 in Javascript I would do this:
var results = testString.split("10")[1].split("20")[0]
Which would return 111213141516171819
However when I do this in VB I get 111
Split(testString,"10")(1).Split("20")(0)
It seems the 2nd split is only recognizing the first character no matter what I put.
So it's stopping when it finds the next "2" in the string, even "2abc" would have the same outcome even though that string doesn't even exist.

String.Split does not have an overload that takes only a String. The argument is a Char array or String array. Your string is probably being converted to a char array. Explicitly pass a string array like so:
testString.Split(New String() { "10" }, StringSplitOptions.None)

Try wrapping the second split so it's fashioned like the first one, i.e.:
Split( Split(testString,"10")(1), "20" )(0)"

Vb treats the delimiter argument only as a single character.

This is a tricky scenario that I have seen trip people up before, so I think it is worth a little more explanation than the other answers give. In your original format Split(testString,"10")(1).Split("20")(0), you are unknowingly using two DIFFERENT Split functions.
The first Split(testString,"10") is using the Microsoft.VisualBasic.Strings.Split function, which takes String type parameters. http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.strings.split(v=vs.110).aspx
The second .Split("20")(0) is using System.String.Split method, which does not have an overload that takes a String parameter. http://msdn.microsoft.com/en-us/library/System.String.Split(v=vs.110).aspx
So what was happening is:
Split(testString,"10") uses Microsoft.VisualBasic.Strings.Split, which
returns new String() {"123456789", "11121314151617181920"}
(1) means get 1st position of the returned array, which is "11121314151617181920"
"11121314151617181920".Split("20")(0) uses System.String.Split, and attempts to split on string separator "20"
NOTE: The string "20" param gets implicitly converted to a char "2" because the only single parameter overload of String.Split has a signature of Public Function Split (ParamArray separator As Char()) As String(). The ParamArray parameter option allows you to pass a comma delimited list of values into the function, similar to how String.Format works with a dynamic # of replacement values. http://msdn.microsoft.com/en-us/library/538f81ec.aspx
Step 3 code becomes "11121314151617181920".Split(new Char() {CChar("20")})(0), which using literal values is "11121314151617181920".Split(new Char() {"2"c})(0). The result is {"111", "13141516171819", "0"}. Get the 0th position, returns "111".
So to avoid confusion, you should convert your code to use the same version of Split on both sides.
Either of the 2 examples below should work:
Example 1: Using Microsoft.VisualBasic.Strings.Split:
Split( Split(testString,"10")(1), "20" )(0)
Example 2: Using System.String.Split:
testString _
.Split(New String() {"10"}, StringSplitOptions.None)(1) _
.Split(New String() {"20"}, StringSplitOptions.None)(0)

Related

How to copy one string's n number of characters to another string in Kotlin?

Let's take a string var str = "Hello Kotlin". I want to copy first 5 character of str to another variable strHello. I was wondering is there any function of doing this or I have to apply a loop and copy characters one by one.
As Tim commented, there's a substring() method which does exactly this, so you can simply do:
val strHello = str.substring(0, 5)
(The first parameter is the 0-based index of the first character to take; and the second is the index of the character to stop before.)
There are many, many methods available on most of the common types.  If you're using an IDE such as IDEA or Eclipse, you should see a list of them pop up after you type str..  (That's one of many good reasons for using an IDE.)  Or check the official documentation.
Please use the string.take(n) utility.
More details at
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/take.html
I was using substring in my project, but it gave an exception when the length of the string was smaller than the second index of substring.
val name1 = "This is a very very long name"
// To copy to another string
val name2 = name1.take(5)
println(name1.substring(0..5))
println(name1.substring(0..50)) // Gives EXCEPTION
println(name1.take(5))
println(name1.take(50)) // No EXCEPTION

Java - Index a String (Substring)

I have this string:
201057&channelTitle=null_JS
I want to be able to cut out the '201057' and make it a new variable. But I don't always know how long the digits will be, so can I somehow use the '&' as a reference?\
myDigits substring(0, position of &)?
Thanks
Sure, you can split the string along the &.
String s = "201057&channelTitle=null_JS";
String[] parts = s.split("&");
String newVar = parts[0];
The expected result here is
parts[0] = "201057";
parts[1] = "channelTitle=null_JS";
In production code you chould check of course the length of the parts array, in case no "&" was present.
Several programming languages also support the useful inverse operation
String s2 = parts.join("&"); // should have same value like s
Alas this one is not part of the Java standard libs, but e.g. Apache Commons Lang features it.
Always read the API first. There is an indexOf method in String that will return you the first index of the character/String you gave it.
You can use myDigits.substring(0, myDigits.indexOf('&');
However, if you want to get all of the arguments in the query separately, then you should use mvw's answer.

How to declare a fixed length string in vb.net without increasing the length during assignment

I have a fixed length string variable:
<VBFixedString(10)>
Public myVar As String
When I assign the var to a value that has 11 chars the var changes length.
This is what I get:
myvar = "1234567890ABCD" ' result = myvar being "1234567890ABCD"
What I want is myvar to be: "1234567890"
and then if it is less than 10 I would like
myvar = "12345" to be "12345 "
I can do this with PadLeft PadRight but was wondering if I can declare it as a fixed length and it would handle all that for you.
and from the old school, LSET will do exactly what you're asking.
myvar = lset("1234567890ABCD",10)
results in "1234567890", while
myvar = lset("12345",10)
results in "12345___" - sorry, the editor trimmed the spaces after the 12345 replaced with underscores
see MSDN entry for LSET
From what I understand the VBFixedString attribute is only recognised by certain file based methods to help structure content written to/read from files. The compiler will not use that attribute for anything else, including to alter how a variable assignment is compiled.
Taken from MSDN:
The VBFixedStringAttribute is informational and cannot be used to
convert a variable length string to a fixed string. The purpose of
this attribute is to modify how strings in structures and non-local
variables are used by methods or API calls that recognize the
VBFixedStringAttribute. Keep in mind that this attribute does not
change the actual length of the string itself.
The last sentence is the important bit:
Keep in mind that this attribute does not change the actual length of the string itself.
http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.vbfixedstringattribute.aspx
EDIT 1:
A quick example on how to auto-padding a string based on a fixed length:
Function FixedLengthString(ByVal value As String, ByVal totalLength As Integer, ByVal padding As Char) As String
Dim length = value.Length
If (length > totalLength) Then Return value.Substring(0, totalLength)
Return value.PadRight(totalLength, padding)
End Function
Here you can pass in a string and if the length of the string is greater than the specified total length you will get a string matching that length. Anything less and you'll get the string plus the padding character upto the specified total length.
This can be improved with error checking and maybe making the method an extension method so you don't have to pass "value".

CStr() vs. Str() vs. .ToString()

I want to know what exactly are the differences between CStr(), Str() and .ToString()?
Label1.Text = CStr(Int(Rnd() * 10))
and
Label1.Text = Str(Int(Rnd() * 10))
and
Label1.Text = Int(Rnd() * 10).ToString
If I use this condition:
If Label1.Text = "7" Then
'Some code here
End If
Str() doesn't work here. What's the difference?
ToString will call the .ToString() function on a particular instance.
In practice, this means that it will throw an exception if the object in
question is Nothing. However, you can implement .ToString() in your own
classes to get a useful string representation of your object, whereas
CType/CStr only work with built-in classes and interfaces.
CStr and CType(expression, String) are exactly equivalent (I'm not
sure where the other poster got the idea that CStr is faster). But they
aren't really functions, they're compiler directives that will emit very
different code depending on the declaration of expression. In most
cases, these directives call a bunch of internal VB code that tries to
get a reasonable string out of expression.
DirectCast(expression, String) assumes that the expression in
question really is a String and just casts it. It's the fastest of all
these options, but will throw an exception if expression is anything
other than a String.
As an Addition to the VBA/VB6 Environment where we have no ToString():
Str() is not aware of international representation. The decimal separator always is a dot (.).
As already mentioned above it prefixes the resulting string with a blank in case of positive values.
There also exists Str$(). The difference to Str() is the return type:
Str() returns a variant of type string, Str$() returns a string.
And Str$() is slightly faster then Str().
CStr() in contrast is aware of international representation. The decimal separator depends on the Windows international settings.
No additional prefixing for positive values will be done.
So if you need to convert a value type to a string and have to ensure a dot as a decimal separator and no prefixing blank, then use this syntax:
Dim d As Double
d = 123.456
Dim s As String
s = Trim(Str$(d))
I don't know about ToString() and i don't know about VB.NET
But in VB6 (Visual Basic 6):
Both of Cstr() and Str() converts values to string. but Cstr() is better because:
Str(): After converting to string it adds 1 space before positive numbers. for example: Str(22) > " 22"
Cstr(): After converting to string it never adds the above extra space - For best result use it with Trim() - Trim(Cstr(Variable))
Although not a problem in the code in the question, it is important to mention that Str() only converts numerical expressions to string, gives an error in other cases, so don't use it for converting values of a cell.
My answer is str() is evil as it always prepends a space for the sign character so if you are comparing values it fails. Instead use CStr() instead which does not do this.
You may comes across business logic that tries to do this:
Eg:
Dim sVar as String = "1"
Dim i as Integer = 1
console.write( cstr(i) = sVar )
Which outputs:
False
I lost a couple hours on this one as the code was quite deep in old code and was very difficult to grok in production environment where logging based debugging was all that was available.

VB.Net Regular expression

I want to have a string in the following format
"FAG001 FAG002 FAG003"
and want to split it into
"FAG001"
"FAG002"
"FAG003"
using a regular expression. Unfortunately my knowledge of regular expression synatax is limited to say teh least. I have tried things like
Dim result = Regex.Split(npcCodes, "([A-Z]3[0-9]3)").ToList
without luck
No need of regex here, you could use String.Split
Dim result As String() = npcCodes.Split(new Char[]{" "})
But if you really want to use regex :
Dim result = Regex.Split(npcCodes, " ").ToList()
As madgnome has pointed out you don't need regular expressions here if the string is always separated with spaces.
However for your information the error you made was that you need curly braces for numeric quantifiers:
[A-Z]{3}
And instead of Regex.Split you can uses Regex.Matches.
The regular expression to use in the Split method would be really simple:
Dim result = Regex.Split(npcCodes, " ").ToList
As the expression only matches a single character, you can just as well use the regular Split method in the String class:
Dim result = npcCodes.Split(" "C).ToList