How to get the last characters of a string - c#

I would like to ask question about formatting strings in C#. Basically I only want to view the last n characters in the string.
For example: string = ("1201 OFFICE PARK RD WDM, APT 708, FLR 2, BLDG 7")
now what i want is just to show:
"APT 708, FLR 2, BLDG 7"
I can actually use a remove method but what if the string.length is not always the same as mentioned in the example? like if I only have "1201 OFFICE PARK" or "FLR 2,BLDG 7" Appreciate any help on this. Thanks!

Following your comments, you can work out n.
string s = "1201 OFFICE PARK RD WDM, APT 708, FLR 2, BLDG 7";
string subS = s.SubString(s.IndexOf(",") + 1).TrimStart();
or if this string is fixed format:
string subS = s.SubString(s.IndexOf(",") + 2);

public string GetEnd (string input, int n)
{
return input.SubString (input.Length - n, n);
}
this should give you the desired result, as long as you know n

Related

How to get a part of string matching a regular expression (c#)?

I have some strings like " 8 2 / 5", "5 5/ 7" and so on, containg math fractions. I need to convert them into doubles. So, how can I get these parts
" 8 "
"2 / 5",
into variables?
var src = " 8 2 / 5";
string base = getBase(src);
string frac = getFrac(src);
// Now base must contain "8" and frac "2/5";
I don't know if some stuff could do this "fraction-to-double" task is already exist (if so, give a link or something), but if I could get these parts into variables I would be able to perform a division and an addition at least.
The simplest approach would be a regex like
(\d) (\d) \/ (\d)
which will work with single digits and all spaces are set correctly. To code to calculate the result could look like
string src = "8 2 / 5";
Regex rx = new Regex(#"(\d) (\d) \/ (\d)");
Match m = rx.Match(src);
if (m.Success)
{
int bs = Convert.ToInt32(m.Groups[1].Value);
int f1 = Convert.ToInt32(m.Groups[2].Value);
int f2 = Convert.ToInt32(m.Groups[3].Value);
double result = bs + (double)f1 / f2;
}
To allow usage of multiple digits and multiple spaces between your numbers you could improve the regex like
(\d*)\s+(\d*)\s+\/\s+(\d*)
To test regexes you can use som online tools like regex101.
Simple Operations : the Regex tested on RegexStorm
String src = " 8 2 / 5";
String Regex = #"([1-9])([0-9]*)([ ])([1-9])([0-9]*)((.)([0-9]+)|)([ ])([- / + *]){1}([ ])([1-9])([0-9]*)((.)([0-9]+)|)";
if(!Regex.IsMatch(src , Regex ))
return;
float Base = float.Parse(Base.Split(" ")[0], CultureInfo.InvariantCulture.NumberFormat);
float Devided= float.Parse(Base.Split(" ")[1], CultureInfo.InvariantCulture.NumberFormat);
float Operator= float.Parse(Base.Split(" ")[2], CultureInfo.InvariantCulture.NumberFormat);
float Denominator= float.Parse(Base.Split(" ")[3], CultureInfo.InvariantCulture.NumberFormat);
//TODO your operation here

Comparing 2 strings c#

So I have a string which I split in half. Now I need to compare both parts of the string and output has to be all the elements that are the same in both of them.
I noticed some people using Intersect, but I don't know why it doesn't work for me, I get really weird output if I use it.
So here is my code:
string first= "1 3 6 8 4 11 34 23 3 1 7 22 24 8"
int firstLength = first.Length;
int half = firstLength / 2;
string S1 = first.Substring(0, half);
string S2= first.Substring(half, half);
var areInCommon = S1.Intersect(S2);
Console.WriteLine("Numbers that these 2 strings have in common are: ");
foreach (int i in areInCommon)
Console.WriteLine(i);
So in this case output would be: 1, 3 and 8.
Any help would be appreciated.
You were close what you really want is arrays of the numbers not arrays of chars... you can get that with the split function.
string first= "1 3 6 8 4 11 34 23 3 1 7 22 24 8"
int firstLength = first.Length;
int half = firstLength / 2;
string S1 = first.Substring(0, half);
string S2= first.Substring(half, half);
var areInCommon = S1.Split(" ".ToArray()).Intersect(S2.Split(" ".ToArray());
Console.WriteLine("Numbers that these 2 strings have in common are: ");
foreach (var i in areInCommon)
Console.WriteLine(i);
A note about using ToArray():
I use ToArray() out of habit and the reason is that if you want to pass in parameters you can't do it without this construct. For example if the data looked like this:
string first= "1, 3, 6, 8, 4, 11, 34, 23, 3, 1, 7, 22, 24, 8"
then we would need to use
.Split(" ,".ToArray(), StringSplitOptions.RemoveEmptyEntries);
since this happens a lot, I use the .ToArray() out of habit. You can also use a new construct (eg new char [] { ' ', ',' } ) I find that more cumbersome, but probably slightly faster.
simply split both the string within an array and them compare both the strings using contains() function.
string implements IEnumerable<char>, thus, you're intersecting sequences of characters instead of strings.
You should use String.Split:
IEnumerable<string> S1 = first.Substring(0, half).Split(' ');
IEnumerable<string> S2= first.Substring(half, half).Split(' ');
And then your intersection will output the desired result.
Also, you can convert each string representation of numbers into integers (i.e. int):
IEnumerable<int> S1 = first.Substring(0, half).Split(' ').Select(s => int.Parse(s));
IEnumerable<int> S2 = first.Substring(half, half).Split(' ').Select(s => int.Parse(s));
You are converting all your characters into integers. The character '1' is not represented by the integer 1. Change your foreach to:
foreach (char i in areInCommon)

How to extract address components from a string?

I have a Xamarin Forms application that uses Xamarin. Mobile on the platforms to get the current location and then ascertain the current address. The address is returned in string format with line breaks.
The address can look like this:
111 Mandurah Tce
Mandurah WA 6210
Australia
or
The Glades
222 Mandurah Tce
Mandurah WA 6210
Australia
I have this code to break it down into the street address (including number), suburb, state and postcode (not very elegant, but it works)
string[] lines = address.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
List<string> addyList = new List<string>(lines);
int count = addyList.Count;
string lineToSplit = addyList.ElementAt(count - 2);
string[] splitLine = lineToSplit.Split(null);
List<string> splitList = new List<string>(splitLine);
string streetAddress = addyList.ElementAt (count - 3).ToString ();
string postCode = splitList.ElementAt(2);
string state = splitList.ElementAt(1);
string suburb = splitList.ElementAt(0);
I would like to extract the street number, and in the previous examples this would be easy, but what is the best way to do it, taking into account the number might be Lot 111 (only need to capture the 111, not the word LOT), or 123A or 8/123 - and sometimes something like 111-113 is also returned
I know that I can use regex and look for every possible combo, but is there an elegant built-in type solution, before I go writing any more messy code (and I know that the above code isn't particularly robust)?
These simple regular expressions will account for many types of address formats, but have you considered all the possible variations, such as:
PO Box 123 suburb state post_code
Unit, Apt, Flat, Villa, Shop X Y street name
7C/94 ALISON ROAD RANDWICK NSW 2031
and that is just to get the number. You will also have to deal with all the possible types of streets such as Lane, Road, Place, Av, Parkway.
Then there are street types such as:
12 Grand Ridge Road suburb_name
This could be interpreted as street = "Grand Ridge" and suburb = "Road suburb_name", as Ridge is also a valid street type.
I have done a lot of work in this area and found the huge number of valid address patterns meant simple regexs didn't solve the problem on large amounts of data.
I ended up develpping this parser http://search.cpan.org/~kimryan/Lingua-EN-AddressParse-1.20/lib/Lingua/EN/AddressParse.pm to solve the problem. It was originally written for Australian addresses so should work well for you.
Regex can capture the parts of a match into groups. Each parentheses () defines a group.
([^\d]*)(\d*)(.*)
For "Lot 222 Mandurah Tce" this returns the following groups
Group 0: "Lot 222 Mandurah Tce" (the input string)
Group 1: "Lot "
Group 2: "222"
Group 3: " Mandurah Tce"
Explanation:
[^\d]* Any number (including 0) of any character except digits.
\d* Any number (including 0) of digits.
.* Any number (including 0) of any character.
string input = "Lot 222 Mandurah Tce";
Match match = Regex.Match(input, #"([^\d]*)(\d*)(.*)");
string beforeNumber = match.Groups[1].Value; // --> "Lot "
string number = match.Groups[2].Value; // --> "222"
string afterNumber = match.Groups[3].Value; // --> " Mandurah Tce"
If a group finds no match, match.Groups[i] will return an empty string ("") for that group.
You could check if the content starts with a number for each entry in the splitLine.
string[] splitLine = lineToSplit.Split(addresseLine);
var streetNumber = string.empty;
foreach(var s in splitLine)
{
//Get the first digit value
if (Regex.IsMatch(s, #"^\d"))
{
streetNumber = s;
break;
}
}
//Deal with empty value another way
Console.WriteLine("My streetnumber is " + s)
Yea I think you have to identify what will work.
If:
it is always in the address line and it must always start with a Digit
nothing else in that line can start with a digit (or if something else does you know which always comes in what order, ie the code below will always work if the street number is always first)
you want every contiguous character to the digit that isn't whitespace (the - and \ examples suggest that to me)
Then it could be as simple as:
var regx = new Regex(#"(?:\s|^)\d[^\s]*");
var mtch = reg.Match(addressline);
You would sort of have to sift and see if any of those assumptions are broken.

I'm trying to get the first two characters of my string to only output on the listbox

I'm trying to get the first two characters of my string to only output on the listbox,
string vin = "1GCHC24U83E614546";
string output = string.Format("{0} {1}",
(vin.Length - 16).ToString(),
(vin.Length - 15).ToString());
lsBox.Items.Add(output.ToString());
What am I doing wrong?
it outputs a "1 2" when I want "1 G"
Because vin contains 17 characters, vin.Length equals 17, and vin.Length - 16 equals 1, and vin.Length - 15 will be 2.
So, your code is equivalent to:
string output = string.Format("{0} {1}",
1.ToString(),
2.ToString());
That's why the string representations will be "1 2". Not "1 G". You will not get first two characters of your string on this process, you will get string representation of two integers with it.
You need to use String.Substring(Int32, Int32) overload like:
string vin = "1GCHC24U83E614546";
string output = vin.Substring(0, 2); // output will be "1G"
If you want to use them in a string.Format, simply you can do;
string output = string.Format("{0} {1}",
vin[0],
vin[1]); // output will be "1 G"
The following is probably less practical than Soner`s answer in your case, but may be useful to know about, e.g. if you want to play around with string.Format():
string vin = "1GCHC24U83E614546";
string output = string.Format("{0} {1}",
vin.First(), // Linq syntax to take first char
vin.Skip(1).First()); // take the second char

Regex masking of words that contain a digit

Trying to come up with a 'simple' regex to mask bits of text that look like they might contain account numbers.
In plain English:
any word containing a digit (or a train of such words) should be matched
leave the last 4 digits intact
replace all previous part of the matched string with four X's (xxxx)
So far
I'm using the following:
[\-0-9 ]+(?<m1>[\-0-9]{4})
replacing with
xxxx${m1}
But this misses on the last few samples below
sample data:
123456789
a123b456
a1234b5678
a1234 b5678
111 22 3333
this is a a1234 b5678 test string
Actual results
xxxx6789
a123b456
a1234b5678
a1234 b5678
xxxx3333
this is a a1234 b5678 test string
Expected results
xxxx6789
xxxxb456
xxxx5678
xxxx5678
xxxx3333
this is a xxxx5678 test string
Is such an arrangement possible with a regex replace?
I think I"m going to need some greediness and lookahead functionality, but I have zero experience in those areas.
This works for your example:
var result = Regex.Replace(
input,
#"(?<!\b\w*\d\w*)(?<m1>\s?\b\w*\d\w*)+",
m => "xxxx" + m.Value.Substring(Math.Max(0, m.Value.Length - 4)));
If you have a value like 111 2233 33, it will print xxxx3 33. If you want this to be free from spaces, you could turn the lambda into a multi-line statement that removes whitespace from the value.
To explain the regex pattern a bit, it's got a negative lookbehind, so it makes sure that the word behind it does not have a digit in it (with optional word characters around the digit). Then it's got the m1 portion, which looks for words with digits in them. The last four characters of this are grabbed via some C# code after the regex pattern resolves the rest.
I don't think that regex is the best way to solve this problem and that's why I am posting this answer. For so complex situations, building the corresponding regex is too difficult and, what is worse, its clarity and adaptability is much lower than a longer-code approach.
The code below these lines delivers the exact functionality you are after, it is clear enough and can be easily extended.
string input = "this is a a1234 b5678 test string";
string output = "";
string[] temp = input.Trim().Split(' ');
bool previousNum = false;
string tempOutput = "";
foreach (string word in temp)
{
if (word.ToCharArray().Where(x => char.IsDigit(x)).Count() > 0)
{
previousNum = true;
tempOutput = tempOutput + word;
}
else
{
if (previousNum)
{
if (tempOutput.Length >= 4) tempOutput = "xxxx" + tempOutput.Substring(tempOutput.Length - 4, 4);
output = output + " " + tempOutput;
previousNum = false;
}
output = output + " " + word;
}
}
if (previousNum)
{
if (tempOutput.Length >= 4) tempOutput = "xxxx" + tempOutput.Substring(tempOutput.Length - 4, 4);
output = output + " " + tempOutput;
previousNum = false;
}
Have you tried this:
.*(?<m1>[\d]{4})(?<m2>.*)
with replacement
xxxx${m1}${m2}
This produces
xxxx6789
xxxx5678
xxxx5678
xxxx3333
xxxx5678 test string
You are not going to get 'a123b456' to match ... until 'b' becomes a number. ;-)
Here is my really quick attempt:
(\s|^)([a-z]*\d+[a-z,0-9]+\s)+
This will select all of those test cases. Now as for C# code, you'll need to check each match to see if there is a space at the beginning or end of the match sequence (e.g., the last example will have the space before and after selected)
here is the C# code to do the replace:
var redacted = Regex.Replace(record, #"(\s|^)([a-z]*\d+[a-z,0-9]+\s)+",
match => "xxxx" /*new String("x",match.Value.Length - 4)*/ +
match.Value.Substring(Math.Max(0, match.Value.Length - 4)));

Categories

Resources