Using GeocodeQuery with Canadian Postal Codes - c#

I am having an issue with Windows Phone 8 Geocoding. Using Microsoft.Phone.Maps.Services.QuerycodeQuery, if I use a full Canadian Postal Code (M5G 1Z4) I get no results. If I use only the first 3 characters (M5G) I get the expected results.
I am not doing anything specific with the data, just passing it to Microsoft for geocoding. Is there a specific reason behind this or is there another way to lookup locations?
Code:
Geocode = new GeocodeQuery()
{
SearchTerm = LocationString,
GeoCoordinate = UserCoordinates ?? new GeoCoordinate(),
MaxResultCount = 1
};
Geocode.QueryCompleted += GetStringLocation_QueryCompleted;
Geocode.QueryCompleted += CleanupGeocode;
Geocode.QueryAsync();

Although this doesn't address the limitation that appears to be in the mapping service's geocode function it is a little workaround that works for me...
When the GetStringLocation_QueryCompleted function returns 0 results I run a regex to check if the search is a valid postal code. If it is one, then I grab the first 3 characters and re-run the geocode.
One thing to make sure of with this approach is that you check to make sure the geocode is not running (IsBusy) when the secondary dispose function is called (if you do it in a separate function)
Regex (Utility.IsPostalCode):
Regex reg = new Regex("^[ABCEGHJ-NPRSTVXY]{1}[0-9]{1}[ABCEGHJ-NPRSTV-Z]{1}[ ]?[0-9]{1}[ABCEGHJ-NPRSTV-Z]{1}[0-9]{1}$",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
return reg.IsMatch(Input);
Within GetStringLocation_QueryCompleted
if (e.Result.Count == 0 && Utility.IsPostalCode(((GeocodeQuery)e.UserState).SearchTerm))
{
if (Geocode != null && Geocode.IsBusy)
Geocode.CancelAsync();
GetStringLocation(((GeocodeQuery)e.UserState).SearchTerm.Substring(0, 3));
}
GetStringLocation would be the function that contains the code that is in the question which accepts a string.

Related

Match string against list of RegEx rules using switch...case statement

I've a code snippet written in JScript.Net for FiddlerScript and trying to re-write the same in C# to use as Fiddler extension. I'm not familiar with C# syntax, so need help.
Here's the existing code snippet in JScript.NET, which I'm trying to convert into C#:
var sHostname = oSession.hostname;
switch(sHostname) {
case /example1.com/i.test(sHostname) && sHostname:
case /example2.com/i.test(sHostname) && sHostname:
case /example3.com/i.test(sHostname) && sHostname:
MessageBox.Show("Matched: " + sHostname);
default:
FiddlerApplication.Log.LogString("No match for hostname.");
}
Here's something I tried in C#, but this is very primitive:
var sHostname = oSession.hostname;
string[] patterns = { #"[a-z]", #"[0-9]", #"example[0-9]", #"[a-z0-9.]", #"\w+" }; // a collection of about 20K+ pattern entries, yes 20K+, and stored in separate class
IList<string> patternList = new ReadOnlyCollection<string>(patterns);
var status = false;
var pattern = "";
foreach (string p in patternList)
{
if (Regex.IsMatch(sHostname, p, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace))
{
pattern = p;
status = true;
break;
}
}
if (status)
{
System.Diagnostics.Debug.WriteLine("Matched: " + pattern);
// Other code
} else
{
System.Diagnostics.Debug.WriteLine("No match found");
// Other code
}
As a newbie to C#, I came across many stuff:
Regex compiled version is better than creating new object every time. I'm not sure specifying switches RegexOptions::Compiled | RegexOptions::IgnoreCase will be same as creating the list once and using over iterations. Any hint on this will be helpful.
Usage of LINQ instead of boilerplate code.
And many more good things in C# world
All I'm interested is a match or not (boolean true / false value), like Any() and not performing any match, split, etc. Again, this code need to be executed over several hundred times per second in Fiddler, so it need to be efficient enough to match against over 20K+ patterns list for a specified input string. I know it sounds bit crazy, so need help from experts.
FYI, I'm using Visual Studio 2013, so not sure if I can use C# 7 syntax. I'd be very much interested if better things can be done in C# 7 or higher VS versions.
Thank you in advance!

How can I get a part/subdomain of my URL in C#?

I have a URL like the following
http://yellowcpd.testpace.net
How can I get yellowcpd from this? I know I can do that with string parsing, but is there a builtin way in C#?
Assuming your URLs will always be testpace.net, try this:
var subdomain = Request.Url.Host.Replace("testpace.net", "").TrimEnd('.');
It'll just give you the non-testpace.net part of the Host. If you don't have Request.Url.Host, you can do new Uri(myString).Host instead.
try this
string url = Request.Url.AbsolutePath;
var myvalues= url.Split('.');
How can I get yellowcpd from this? I know I can do that with string
parsing, but is there a builtin way in C#?
.Net doesn't provide a built-in feature to extract specific parts from Uri.Host. You will have to use string manipulation or a regular expression yourself.
The only constant part of the domain string is the TLD. The TLD is the very last bit of the domain string, eg .com, .net, .uk etc. Everything else under that depends on the particular TLD for its position (so you can't assume the next to last part is the "domain name" as, for .co.uk it would be .co
This fits the bill.
Split over two lines:
string rawURL = Request.Url.Host;
string domainName = rawURL .Split(new char[] { '.', '.' })[1];
Or over one:
string rawURL = Request.Url.Host.Split(new char[] { '.', '.' })[1];
The simple answer to your question is no there isn't a built in method to extract JUST the sub-domain. With that said this is the solution that I use...
public enum GetSubDomainOption
{
ExcludeWWW,
IncludeWWW
};
public static class Extentions
{
public static string GetSubDomain(this Uri uri,
GetSubDomainOption getSubDomainOption = GetSubDomainOption.IncludeWWW)
{
var subdomain = new StringBuilder();
for (var i = 0; i < uri.Host.Split(new char[]{'.'}).Length - 2; i++)
{
//Ignore any www values of ExcludeWWW option is set
if(getSubDomainOption == GetSubDomainOption.ExcludeWWW && uri.Host.Split(new char[]{'.'})[i].ToLowerInvariant() == "www") continue;
//I use a ternary operator here...this could easily be converted to an if/else if you are of the ternary operators are evil crowd
subdomain.Append((i < uri.Host.Split(new char[]{'.'}).Length - 3 &&
uri.Host.Split(new char[]{'.'})[i+1].ToLowerInvariant() != "www") ?
uri.Host.Split(new char[]{'.'})[i] + "." :
uri.Host.Split(new char[]{'.'})[i]);
}
return subdomain.ToString();
}
}
USAGE:
var subDomain = Request.Url.GetSubDomain(GetSubDomainOption.ExcludeWWW);
or
var subDomain = Request.Url.GetSubDomain();
I currently have the default set to include the WWW. You could easilly reverse this by switching the optional parameter value in the GetSubDomain() method.
In my opinion this allows for an option that looks nice in code and without digging in appears to be 'built-in' to c#. Just to confirm your expectations...I tested three values and this method will always return just the "yellowcpd" if the exclude flag is used.
www.yellowcpd.testpace.net
yellowcpd.testpace.net
www.yellowcpd.www.testpace.net
One assumption that I use is that...splitting the hostname on a . will always result in the last two values being the domain (i.e. something.com)
As others have pointed out, you can do something like this:
var req = new HttpRequest(filename: "search", url: "http://www.yellowcpd.testpace.net", queryString: "q=alaska");
var host = req.Url.Host;
var yellow = host.Split('.')[1];
The portion of the URL you want is part of the hostname. You may hope to find some method that directly addresses that portion of the name, e.g. "the subdomain (yellowcpd) within TestSpace", but this is probably not possible, because the rules for valid host names allow for any number of labels (see Valid Host Names). The host name can have any number of labels, separated by periods. You will have to add additional restrictions to get what you want, e.g. "Separate the host name into labels, discard www if present and take the next label".

Find index of first Char(Letter) in string

I have a mental block and can't seem to figure this out, sure its pretty easy 0_o
I have the following string: "5555S1"
String can contain any number of digits, followed by a Letter(A-Z), followed by numbers again.
How do I get the index of the Letter(S), so that I can substring so get everything following the Letter
Ie: 5555S1
Should return S1
Cheers
You could also check if the integer representation of the character is >= 65 && <=90.
Simple Python:
test = '5555Z187456764587368457638'
for i in range(0,len(test)):
if test[i].isalpha():
break
print test[i:]
Yields: Z187456764587368457638
Given that you didn't say what language your using I'm going to pick the one I want to answer in - c#
String.Index see http://msdn.microsoft.com/en-us/library/system.string.indexof.aspx for more
for good measure here it is in java string.indexOf
One way could be to loop through the string untill you find a letter.
while(! isAlpha(s[i])
i++;
or something should work.
This doesn't answer your question but it does solve your problem.
(Although you can use it to work out the index)
Your problem is a good candidate for Regular Expressions (regex)
Here is one I prepared earlier:
String code = "1234A0987";
//timeout optional but needed for security (so bad guys dont overload your server)
TimeSpan timeout = TimeSpan.FromMilliseconds(150);
//Magic here:
//Pattern == (Block of 1 or more numbers)(block of 1 or more not numbers)(Block of 1 or more numbers)
String regexPattern = #"^(?<firstNum>\d+)(?<notNumber>\D+)(?<SecondNum>\d+)?";
Regex r = new Regex(regexPattern, RegexOptions.None, timeout);
Match m = r.Match(code);
if (m.Success)//We got a match!
{
Console.WriteLine ("SecondNumber: {0}",r.Match(code).Result("${SecondNum}"));
Console.WriteLine("All data (formatted): {0}",r.Match(code).Result("${firstNum}-${notNumber}-${SecondNum}"));
Console.WriteLine("Offset length (not that you need it now): {0}", r.Match(code).Result("${firstNum}").Length);
}
Output:
SecondNumber: 0987
All data (formatted): 1234-A-0987
Offset length (not that you need it now): 4
Further info on this example here.
So there you go you can even work out what that index was.
Regex cheat sheet

Pulling the Video ID of a YouTube video using substrings

I am currently trying to extract the ID of a YouTube video from the embed url YouTube supplies.
I am currently using this as an example:
<iframe width="560" height="315" src="http://www.youtube.com/embed/aSVpBqOsC7o" frameborder="0" allowfullscreen></iframe>
So far my code currently looks like this,
else if (TB_VideoLink.Text.Trim().Contains("http://www.youtube.com/embed/"))
{
youtube_url = TB_VideoLink.Text.Trim();
int Count = youtube_url.IndexOf("/embed/", 7);
string cutid = youtube_url.Substring(Count,youtube_url.IndexOf("\" frameborder"));
LB_VideoCodeLink.Text = cutid;
}
I Seem to be getting there, however the code falls over on CutID and I am not sure why???
Cheers
I always find it much easier to use regular expressions for this sort of thing, Substringand IndexOf always seem dated to me, but that's just my personal opinion.
Here is how I would solve this problem.
Regex regexPattern = new Regex(#"src=\""\S+/embed/(?<videoId>\w+)");
Match videoIdMatch = regexPattern.Match(TB_VideoLink.Text);
if (videoIdMatch.Success)
{
LB_VideoCodeLink.Text = videoIdMatch.Groups["videoId"].Value;
}
This will perform a regular expression match, locating src=", ignoring all characters up until /embed/ then extracting all the word characters after it as a named group.
You can then get the value of this named group. The advantage is, this will work even if frameborder does not occur directly after the src.
Hope this is useful,
Luke
The second parameter of the Substring method is length, not second index. Subtract the index of the second test from the first to get the required length.
else if (TB_VideoLink.Text.Trim().Contains("http://www.youtube.com/embed/"))
{
youtube_url = TB_VideoLink.Text.Trim();
// Find the start of the embed code
int Count = youtube_url.IndexOf("/embed/", 7);
// From the start of the embed bit, search for the next "
int endIndex = youtube_url.IndexOf("\"", Count);
// The ID is from the 'Count' variable, for the next (endIndex-Count) characters
string cutid = youtube_url.Substring(Count, endIndex - Count);
LB_VideoCodeLink.Text = cutid;
}
You probably should have some more exception handling for when either of the two test strings do not exist.
Similar to answer above, but was beaten to it.. doh
//Regex with YouTube Url and Group () any Word character a-z0-9 and expect 1 or more characters +
var youTubeIdRegex = new Regex(#"http://www.youtube.com/embed/(?<videoId>\w+)",RegexOptions.IgnoreCase|RegexOptions.Compiled);
var youTubeUrl = TB_VideoLink.Text.Trim();
var match = youTubeIdRegex.Match(youTubeUrl);
var youTubeId = match.Groups["videoId"].Value; //Group[1] is (\w+) -- first group ()
LB_VideoCodeLink.Text = youTubeId;

Parsing an inconsistent log file

I have a log file that I want to parse and load into a database. I'm struggling with the best way to go about parsing it.
The log file is in the format Category: Information
Case Number: CASE01
User ID: JOSM
Software: Microsoft Word
Date Started: 21-01-2010
Date Ended: 22-01-2010
Thing is, there's other bits and pieces thrown into the log file that mean the information isn't always present on the same line. I also only want the information, not the category.
So far, I've tried stick it all into an array separated by \r\n, but I have to know the index of the information I want in order to consistently retrieve it, and that changes. I've also tried feeding it through StreamReader and saying
if (line.Contains("Case Number"))
{
tbReport.AppendText("Case Number: " + line.Remove(0, 13) + "\r\n");
}
Which gets me the information I want, but makes it very hard to do anything with.
I feel I'm better off going down the array path, but I could do with some guidance on how to search the array for the the category, and then parse the information.
Once I can parse it accurately, adding it into a database should be fairly straight forward. As it's my first time attempting this, I'd be interested in any tips or guidance as to the best way to go about this though.
Thanks.
This will give you a collection with all key/value pairs.
List<KeyValuePair> items = new List<KeyValuePair>();
var line = reader.ReadLine();
while (line != null)
{
int pos = line.IndexOf(':');
items.Add(new KeyValuePair(line.Substring(0, pos), line.Substring(pos+1));
line = reader.ReadLine();
}
If you have a log class which contains all possible names as properties, you can use reflection instead:
class LogEntry
{
public string CaseNumber { get; set; }
public string User { get; set; }
public string Software{ get; set; }
public string DateStarted { get; set; }
public string DateEnded { get; set; }
}
List<LogEntry> items = new List<LogEntry>();
var line = reader.ReadLine();
var currentEntry = new LogEntry();
while (line != null)
{
if (line == "") //empty line = new log entry. Change to your delimiter.
{
items.Add(currentEntry);
currentEntry = new LogEntry();
}
int pos = line.IndexOf(':');
var name = line.Substring(0, pos).Replace(" ", string.Empty);
var value = line.Substring(pos+1);
var pi = entry.GetType().GetProperty(name);
pi.SetValue(entry, value, null);
line = reader.ReadLine();
}
Note that I've not tested the code (just written it directly in here). You have to add error checking and such. The last alternative is not very performant as it is, but should do OK.
Sounds like a good case candidate for RegExp :
http://www.regular-expressions.info/dotnet.html
They're not too easy to learn but once you get the basic understanding, they can't be beaten for that kind of tasks.
It's not really a simple answer, but have you maybe though about using a regular expression for parsing the information out?
Regular expressions is kinda hardcore stuff, but they can parsed advanced files quite easily.
So in what I can see, then its like:
If a line starts with A-Z, then (a-z or A-Z or 0-9 or space) from zero to many times, then followed by a : then a space, and then the value.
So if you make a regular expression for that (If you wait awhile I will try to make one for you), then you could test each line with that. If it matches, then we can also use regular expressions to take the last part out, and the "key". If it don't matches, then we just append it to the last key.
Beware that its not totally fool-proof, as a new line could just start this way, but its kinda the best thing we can do, i think.
As promised here is a starting point for your regular expression:
^(?'key'[A-Z][a-z,A-Z,0-9,\s]+):\s(?'value'.+)
So to try and tell what it does, we need to go though each part:
^ ensures that a match starts on the beginning of a line
(?'key' is a syntax to begin a "capture" group. The regular expression will then give us access to easily take the "key" part of the regular expression out.
We that with a [A-Z] - that is a group that will match any big letter. But only one
[a-z,A-Z,0-9,\s]+ - is like the previous group, but just for all big, or small letters, numbers and space (\s), the plus outside the group tells that it can match more than one.
Then we just end the group, and puts in out *: and then a space.
We then begin a new group the value group, just like the key group.
Then we just write . (that means everything), and then just a + after that to make it catch more than one
I actually think that you can just take the whole string, and just match a:
RegEx.Matches (or something like that), and loop over them.
Then just take match.Groups["key"] and match.Groups["value"] and put into your array. (Sorry i dont have a Visual Studio handy to test it out)

Categories