Format a string into columns - c#

Is there a cool way to take something like this:
Customer Name - City, State - ID
Bob Whiley - Howesville, TN - 322
Marley Winchester - Old Towne, CA - 5653
and format it to something like this:
Customer Name - City, State - ID
Bob Whiley - Howesville, TN - 322
Marley Winchester - Old Towne, CA - 5653
Using string format commands?
I am not too hung up on what to do if one is very long. For example this would be ok by me:
Customer Name - City, State - ID
Bob Whiley - Howesville, TN - 322
Marley Winchester - Old Towne, CA - 5653
Super Town person - Long Town Name, WA- 45648
To provide some context. I have a drop down box that shows info very similar to this. Right now my code to create the item in the drop down looks like this:
public partial class CustomerDataContract
{
public string DropDownDisplay
{
get
{
return Name + " - " + City + ", " + State + " - " + ID;
}
}
}
I am looking for a way to format this better. Any ideas?
This is what I ended up with:
HttpContext.Current.Server.HtmlDecode(
String.Format("{0,-27} - {1,-15}, {2, 2} - {3,5}",
Name, City, State, ID)
.Replace(" ", " "));
The HtmlDecode changes the to a space that can withstand the space removing formatting of the dropdown list.

You can specify the number of columns occupied by the text as well as alignment using Console.WriteLine or using String.Format:
// Prints "--123 --"
Console.WriteLine("--{0,-10}--", 123);
// Prints "-- 123--"
Console.WriteLine("--{0,10}--", 123);
The number specifies the number of columns you want to use and the sign specifies alignment (- for left alignment, + for right alignment). So, if you know the number of columns available, you could write for example something like this:
public string DropDownDisplay {
get {
return String.Format("{0,-10} - {1,-10}, {2, 10} - {3,5}"),
Name, City, State, ID);
}
}
If you'd like to calculate the number of columns based on the entire list (e.g. the longest name), then you'll need to get that number in advance and pass it as a parameter to your DropDownDisplay - there is no way to do this automatically.

In addition to Tomas's answer I just want to point out that string interpolation can be used in C# 6 or newer.
// with string format
var columnHeaders1 = string.Format($"|{0,-30}|{1,-4}|{2,-15}|{3,-30}|{4,-30}|{5,-30}|{6,-30}", "ColumnA", "ColumnB", "ColumnC", "ColumnD", "ColumnE", "ColumnF", "ColumnG");
// with string interpolation
var columnHeaders2 = $"|{"ColumnA",-30}|{"ColumnB",-4}|{"ColumnC",-15}|{"ColumnD",-30}|{"ColumnE",-30}|{"ColumnF",-30}|{"ColumnG",-30}";

I am unable to add a comment above, but in the accepted answer it was stated:
If you'd like to calculate the number of columns based on the entire list (e.g. the longest name), then you'll need to get that number in advance and pass it as a parameter to your DropDownDisplay - there is no way to do this automatically.
This can in fact be done programmatically at runtime by creating the format string 'on the fly':
string p0 = "first";
string p1 = "separated by alignment value x";
int x = n * 10; // calculate the alignment x as needed
// now use x to give something like: {0,-20}, {1}
string fmt = "{0,-" + x + "},{1}"; // or whatever formatting expression you want
// then use the fmt string
string str = string.Format(fmt, p0, p1)
// with n = 2 this would give us
"first ,separated by alignment value x"

Related

C#, label ignores parts of the given text

i need to put in my label something like "x rub | y%" but label ignores the rest of text after the x.
when the label gets "0" value, it works as i want it to, i.e. "0$. | 0%", but whenever the value isnt 0, it only displays "read_cat"'s value ("2000"). Thank you in advance.
System.IO.StreamReader reading2 = File.OpenText("categories\\clothes.txt");
read_cat1 = Convert.ToString(File.ReadAllText("categories\\clothes.txt"));
clothes_percentage.Text = Convert.ToString(read_cat1) +"$ | "+
Convert.ToString(Math.Round(Convert.ToDouble(read_cat1) * 100 / salary, 2))+"%";
reading2.Close();
My guess is that your file contains a linebreak after the actual value. Use the Trim() method to remove linebreaks and other whitespace from the string you read from the file.
string read_cat1 = File.ReadAllText("categories\\clothes.txt");
read_cat1 = read_cat1.Trim();
clothes_percentage.Text = read_cat1 + "$ | " +
Math.Round(Convert.ToDouble(read_cat1) * 100 / salary, 2) +"%";

listBox is not displaying manual string inside it, but displaying the 'str' value

Firstly What the hell is that, I think there is no any expression for it but I am asking you specialists:
string onUserName = msj.Substring(3);
lstMsjClient.Items.Add(onUserName + "is online now.");
Here the onUserName can be displayed inside the lstMsjClient but the "is online now" can not be displayed inside the lstMsjClient.
So is not that funny, what is the reason ?
That's soooo interesting.
if you use
string msj = "One";
string onUserName = msj.Substring(3);
lstMsjClient.Items.Add(onUserName + "is online now.");
//O is 0
//n is 1
//e is 2
//after blank 3. index
Output : "is online now."
because Substring(3) mean index start 3.
if you want first 3 chars you must use Substring(0,3)
try this code
string msj = "OneTwoThree";
string onUserName = msj.Substring(3);
listBox1.Items.Add(onUserName + "is online now.");
Output : "TwoThreeis online now." ok?

Retain 0 in front of a number

I need help figuring out a logic.
I have a working code where the code will take a string and figure out every numbers in that string then add 1.
string str = "";
str = Console.ReadLine();
str = Regex.Replace(
str,
#"\d+",
m => (Double.Parse(m.Groups[0].Value) + 1).ToString()
);
Example:
If I enter "User 000079 is making $1000 from Jan 02 to Feb 24".
The code will produce output: "User 80 is making $1001 from Jan 3 to Feb 25".
The problem is, I want to keep the 0 in front of the 80 and 3. (i.e. User 000080 is making $1001 from Jan 03 to Feb 25)
How do I do that?
Additional Info: Let me clarify, this is just an example. What I want is just a way to add 1 to every number appearing in the string. So if it means UserID, January 31 - Yes, I still want them to increase by 1
This will do what you need:
string str = Console.ReadLine();
str = Regex.Replace(
str,
#"\d+",
m => (Double.Parse(m.Groups[0].Value) + 1).ToString().PadLeft(m.Groups[0].Value.Length, '0')
);
You can fix this with the ToString format like below:
String x = (50).ToString("D8"); // "00000050"
You can find more info about this here: msdn
edit: About the lengte if you do this the length will be correct:
System.Text.RegularExpressions.Regex.Replace(
str,
#"\d+",
m => (int.Parse(m.Groups[0].Value) + 1).ToString("D" + m.Groups[0].Value.Length)
);
It sounds like your user ID numbers aren't really 'numbers', but rather strings of numeric characters. Can the representation of the ID be changed to a string instead?
If you only care about the extra zeroes when rendering the ID, you can use String.Format to render the numeric value correctly using Custom Numeric Formats (specifically, see the 'Zero Placeholder' section).

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.

Format text by adding whitespace

I am trying to format strings by whitespaces.
All strings normally look like
01. Anton 30p
02. Cinderella 20p
03. Thomas 18p
04. Anastacia-Laura 16p
I want to format each string, that the points start at the same column.
There I wrote:
s = stringUpToName;
int addSpacing = 37 - s.Length;
for (int i = 0; i < addSpacing; i += 1) s += " ";
s += points;
It gets closer this way, but it's still not perfectly formatted.
I want it to look like this:
01. Anton 30p
02. Cinderella 20p
03. Thomas 18p
04. Anastacia-Laura 16p
Use "0" custom specifier as zero-placeholder symbol to format index/number of record. 0:00 will give you 01 for value 1.
Also keep in mind that item format syntax is { index[,alignment][:formatString]} where alignment indicates preferred formatted field width. So, adding alignment to second item format {1,20} gives you right-aligned field width of 20 characters. With negative alignment field will be left-aligned.
Total format string will look like "{0:00}. {1,-20}{2}p"
You can use it with String.Format or StringBuilder.AppendFormat if you are build string, or Console.WriteLine if you are writing it to console.
int index = 1;
string name = "Anton";
int points = 30;
var result = String.Format("{0:00}. {1,-20}{2}p", index, name, points)
// "01. Anton 30p"
String.Format and Composite Formatting using the Alignment functionality
string[] names = new string[]
{
"1. Anton 30p",
"2. Cinderella 20p",
"3. Thomas 18p",
"4. Anastacia-Laura 16p"
};
foreach(string s in names)
{
int lastSpace = s.LastIndexOf(' ');
int firstSpace = s.IndexOf(' ');
string result = string.Format("{0,-4}{1,-37}{2,4}", s.Substring(0, firstSpace), s.Substring(firstSpace + 1, lastSpace), s.Substring(lastSpace+1));
Console.WriteLine(result);
}
Keep in mind that to see the output exactly aligned in columns you need to use a Fixed Width font like Lucida Console or Courier, because fonts with variable width use less pixel to print an I than to print a W.
Try right-align the numbers using
String.Format("{0} {1} {2,4}p",
Num,
Name,
Point);

Categories

Resources