Using perl regex constructs in VB.Net? - vb.net

In perl you can write
$string =~ tr/[a,e,i,o,u,y]/[A,E,I,O,U,Y]/;
for example.
Is it possible to achieve the same "translation" effects with VB.Net regexes?
Thanks you!
PS: I'm not searching for a way to port this very example, it's more of a curiosity question :)

There is no standard method for this. You can do it by iterating over each character in your input string and using a dictionary to map it to another character (or leave it unchanged if the character is not found in the dictionary). The result can be built using a StringBuilder for performance reasons.
If performance is not an issue then you might be able to use a few replace operations instead:
s = s.Replace("a", "A")
.Replace("e", "E")
...
.Replace("y", "Y");

Here's one way to do this:
public string fakeTR(string theString, char[] org, char[] rep)
{
for(int i=0;i<org.lenght;i++)
{
theString = theString.Replace(org[i], rep[i]);
}
return theString;
}
You would be able to call it with somewhat clunky but shorter:
string v = "Black in South Dakota";
v = fakeTR(v, new char[]{'B','l','a','c','k'}, new char[]{'W','h','i','t','e'});
H/T http://discuss.joelonsoftware.com/default.asp?dotnet.12.306220.6

Related

How to serialize an object with newtonsoft, which has a value with backslash [\]

I prepared this small example to show you my problem (vb.net and Newtonsoft)
I would prefer that the solution be done with Newtonsoft.
Public Class Message
Property Emoji As String
End Class
Public Sub GetJson()
Dim msgObject As New Message With {.Emoji = "\uD83D\uDE00"}
'Option 1
Dim JsonSerializerSettings As New JsonSerializerSettings
JsonSerializerSettings.StringEscapeHandling = StringEscapeHandling.EscapeNonAscii
Dim msgJson_1 As String = Newtonsoft.Json.JsonConvert.SerializeObject(msgObject, JsonSerializerSettings)
'Option 2
Dim msgJson_2 As String = Newtonsoft.Json.JsonConvert.SerializeObject(msgObject, Newtonsoft.Json.Formatting.None)
'Option 3
Dim stringWriter As New StringWriter()
Using writer As New JsonTextWriter(stringWriter)
writer.Formatting = Formatting.None
Dim serializer As New JsonSerializer()
serializer.Serialize(writer, msgObject)
End Using
Dim msgJson_3 As String = stringWriter.ToString()
End Sub
with none of the three options works, it always results in
{
"Emoji": "\\uD83D\\uDE00"
}
The result I need is
{
"Emoji": "\uD83D\uDE00"
}
How do I set Newtonsoft to not take into account the backslash character, as an escaped character?
Another unorthodox way could be:
jsonString = jsonString.replace("\\","\")
I do not really like
Thanks!!!!
\ is an escape char in JSON hence if you try and serialise a \ it gets escaped as \\ then when you deserialise \\ you get \
My guess is you have been given an example asking you to send "Emoji": "\uD83D\uDE00"
In json (and C#) \u#### specifies a unicode character (usually for something not found on a keyboard) as you are using VB.NET instead you should use $"{ChrW(&HD83D)}{ChrW(&HDE00)}"
"jsonString = jsonString.replace("//","/") " will never work, this is more safe way
json = json.Replace("\\\\u","\\u");
or since you don't like old, good classical solutions
json = Regex.Replace(json, #"\\u", #"u");
//or
json = json.Replace(#"\\u", #"\u");
even this will work in your case ( but I will not recommend for another cases since it is not safe)
json = Regex.Unescape(json);

Getting the name of the variable as a string in GD Script

I have been looking for a solution everywhere on the internet but nowhere I can see a single script which lets me read the name of a variable as a string in Godot 3.1
What I want to do:
Save path names as variables.
Compare the name of the path variable as a string to the value of another string and print the path value.
Eg -
var Apple = "mypath/folder/apple.png"
var myArray = ["Apple", "Pear"]
Function that compares the Variable name as String to the String -
if (myArray[myposition] == **the required function that outputs variable name as String**(Apple) :
print (Apple) #this prints out the path.
Thanks in advance!
I think your approach here might be a little oversimplified for what you're trying to accomplish. It basically seems to work out to if (array[apple]) == apple then apple, which doesn't really solve a programmatic problem. More complexity seems required.
First, you might have a function to return all of your icon names, something like this.
func get_avatar_names():
var avatar_names = []
var folder_path = "res://my/path"
var avatar_dir = Directory.new()
avatar_dir.open(folder_path)
avatar_dir.list_dir_begin(true, true)
while true:
var avatar_file = avatar_dir.get_next()
if avatar_file == "":
break
else:
var avatar_name = avatar_file.trim_suffix(".png")
avatar_names.append(avatar_name)
return avatar_names
Then something like this back in the main function, where you have your list of names you care about at the moment, and for each name, check the list of avatar names, and if you have a match, reconstruct the path and do other work:
var some_names = ["Jim","Apple","Sally"]
var avatar_names = get_avatar_names()
for name in some_names:
if avatar_names.has(name):
var img_path = "res://my/path/" + name + ".png"
# load images, additional work, etc...
That's the approach I would take here, hope this makes sense and helps.
I think the current answer is best for the approach you desire, but the performance is pretty bad with string comparisons.
I would suggest adding an enumeration for efficient comparisons. unfortunately Godot does enums differently then this, it seems like your position is an int so we can define a dictionary like this to search for the index and print it out with the int value.
var fruits = {0:"Apple",1:"Pear"}
func myfunc():
var myposition = 0
if fruits.has(myposition):
print(fruits[myposition])
output: Apple
If your position was string based then an enum could be used with slightly less typing and different considerations.
reference: https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/gdscript_basics.html#enums
Can't you just use the str() function to convert any data type to stirng?
var = str(var)

optimize a string.Format + replace

I have this function. The visual studio profile marked the line with string.Format as hot and were i spend much of my time.
How can i write this loop more efficiently?
public string EscapeNoPredicate(string sz)
{
var s = new StringBuilder(sz);
s.Replace(sepStr, sepStr + sepStr);
foreach (char v in IllegalChars)
{
string s2 = string.Format("{0}{1:X2}", seperator, (Int16)v);
s.Replace(v.ToString(), s2);
}
return s.ToString();
}
Instead of calculating s2s foreach v each time this method is called; you can store them precalculated. Of course I am assuming IllegalChars and seperator remains same.
In a string.format you can put objects, so (Int16)v is not needed. You can supply "v"

Add 10000 to numbers using Regex replace?

I need to replace some 2- and 3-digit numbers with the same number plus 10000. So
Photo.123.aspx
needs to become
Photo.10123.aspx
and also
Photo.12.aspx
needs to become
Photo.10012.aspx
I know that in .NET I can delegate the replacement to a function and just add 10000 to the number, but I'd rather stick to garden-variety RegEx if I can. Any ideas?
James is right that you want to use the Regex.Replace method that takes a MatchEvaluator argument. The match evaluator delegate is where you can take the numeric string you get in the match and convert it into a number that you can add 10,000 to. I used a lambda expression in place of the explicit delegate because its more compact and readable.
using System;
using System.Text.RegularExpressions;
namespace RenameAspxFile
{
sealed class Program
{
private static readonly Regex _aspxFileNameRegex = new Regex(#"(\S+\.)(\d+)(\.aspx)", RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);
private static readonly string[] _aspxFileNames= {"Photo.123.aspx", "Photo.456.aspx", "BigPhoto.789.aspx"};
static void Main(string[] args)
{
Program program = new Program();
program.Run();
}
void Run()
{
foreach (string aspxFileName in _aspxFileNames)
{
Console.WriteLine("Renamed '{0}' to '{1}'", aspxFileName, AddTenThousandToPhotoNumber(aspxFileName));
}
}
string AddTenThousandToPhotoNumber(string aspxFileName)
{
return _aspxFileNameRegex.Replace(aspxFileName, match => String.Format("{0}{1}{2}", match.Result("$1"), Int32.Parse(match.Result("$2")) + 10000, match.Result("$3")));
}
}
}
I think that using a RegEx for the match, and a function for the replace is most appropriate in this case, you are doing simple math, use something that is designed to do it.....
Is there any reason it has to be VB.NET?
Perl
s(
Photo\. (\d{2,3}) \.aspx
){
"Photo." . ($1 + 10000) . ".aspx"
}xe
Try the following:
"Photo\./d\.aspx" and replace with "Photo.1000$1.aspx"
"Photo\./d/d\.aspx" and replace with "Photo.100$1.aspx"
"Photo\./d/d/d\.aspx" and replace with "Photo.10$1.aspx"
That is the only way I see this happening.
If it's only two or three digit numbers:
(I assume you are using .NET Regex since we are talking about .aspx files)
Check for: Photo\.{\d\d\d}\.aspx
Replace with: Photo.10\1.aspx
Then check against: Photo\.{\d\d}\.aspx
Replace with: Photo.100\1.aspx
James Curran did it little faster than me but well here is what I have for you. Think it's the smallest code you can have with Regex to do what you want.
Regex regex = new Regex(#"(\d\d\d?)", RegexOptions.None);
string result = regex.Replace(#"Photo.123.asp", delegate(Match m)
{
return "Photo.1"
+ m.Groups[1].Captures[0].Value.PadLeft(4, '0')
+ ".aspx";
}
);
did you try just using PadLeft?
This appears to do what you want:
static public string Evaluator(Match match)
{
return "Photo.1"
+ match.Groups[1].Captures[0].Value.PadLeft(4, '0')
+ ".aspx";
}
public void Code(params string[] args)
{
string pattern = #"Photo\.([\d]+)\.aspx";
string test = "Photo.123.aspx";
Regex regex = new Regex(pattern);
string converted = regex.Replace(test, Evaluator)
Console.WriteLine(converted);
}
This will match the right part of the string, but won't tell you if it's two digits or three.
[^\d][\d]{2,3}[^\d]
Still, you could use that to grab the number, convert it to an int, add 10000, and convert that to the string you need.
Found this question since I was trying to do something similar in Vim.
Ill put the solution here.
:s/Photo\.\d\+\.aspx/\=Photo\.submatch(0)+10000\.aspx/g

What is the best way to access an array inside Velocity?

I have a Java array such as:
String[] arr = new String[] {"123","doc","projectReport.doc"};
In my opinion the natural way to access would be:
#set($att_id = $arr[0])
#set($att_type = $arr[1])
#set($att_name = $arr[2])
But that it is not working. I have come with this workaround. But it a bit too much code for such an easy task.
#set($counter = 0)
#foreach($el in $arr)
#if($counter==0)
#set($att_id = $el)
#elseif($counter==1)
#set($att_type = $el)
#elseif($counter==2)
#set($att_name = $el)
#end
#set($counter = $counter + 1)
#end
Is there any other way?
You can use use Velocity 1.6: for an array named $array one can simply do $array.get($index).
In the upcoming Velocity 1.7, one will be able to do $array[$index] (as well as $list[$index] and $map[$key]).
You could wrap the array in a List using Arrays.asList(T... a). The new List object is backed by the original array so it doesn't wastefully allocate a copy. Even changes made to the new List will propagate back to the array.
Then you can use $list.get(int index) to get your objects out in Velocity.
If you need to get just one or two objects from an array, you can also use Array.get(Object array, int index)
to get an item from an array.
String[] arr = new String[] {"123", "doc", "projectReport.doc"};
In my opinion the natural way to access would be:
#set($att_id = $arr[0])
#set($att_type = $arr[1])
#set($att_name = $arr[2])
The value for this can be get by using $array.get("arr", 1) because there is no direct way to get the value from array like $att_id = $arr[0] in velocity.
Hope it works :)
Velocity 1.6
$myarray.isEmpty()
$myarray.size()
$myarray.get(2)
$myarray.set(1, 'test')
http://velocity.apache.org/engine/1.7/user-guide.html
there is an implicit counter $velocityCount which starts with value 1 so you do not have to create your own counter.
Brian's answer is indeed correct, although you might like to know that upcoming Velocity 1.6 has direct support for arrays; see the Velocity documentation for more information.
I ended up using the ListTool from the velocity-tools.jar. It has methods to access an array's elements and also get its size.
I has the same question and it got answered on another thread
#set ( $Page = $additionalParams.get('Page') )
#set ( $Pages = [] )
#if ( $Page != $null && $Page != "" )
#foreach($i in $Page.split(";"))
$Pages.add($i)
#end
#end
Array indexing in Confluence / Velocity templates