Concatenate strings together starting at specific position - c#

I want to concatenate multiple strings together but shown in a neat way.
Example
Record[1] Title : xxxxxx Date : dd/mm/yy
Record[1000] Title : xxxxxx Date : dd/mm/yy
If i just concatenate the strings together as the record number increases the Title and Date would be pushed across the screen looking messy(shown above). I want the Title and Date to always start at certain position (say position 25) in the string so no matter the number of the record length is the Title and Date will align down the page.
This string will update the Treeview node text.

Consider using composite formatting, specifically the alignment parameter of the format string.
The optional alignment component is a signed integer indicating the preferred formatted field width. If the value of alignment is less than the length of the formatted string, alignment is ignored and the length of the formatted string is used as the field width. The formatted data in the field is right-aligned if alignment is positive and left-aligned if alignment is negative. If padding is necessary, white space is used. The comma is required if alignment is specified.
var s="";
foreach (var item in col) {
s += String.Format("Record[{0,-6}] Title: {1,-15} Date: {2}", item.ID, item.Title, item.Date);
}
Example using StringBuilder for effeciency:
var sb = new StringBuilder();
foreach (var item in col) {
sb.AppendFormat("Record[{0,-6}] Title: {1,-15} Date: {2}", item.ID, item.Title, item.Date);
}

You can use PadRight() to ensure your first string has the right length:
var record = "Record[1]";
var title = "Title : xxxxxx Date : dd/mm/yy .";
var output = record.PadRight(25) + title;

This works for me:
var paddingRecord = items.Select(x => x.Record.ToString().Length).Max();
var paddingTitle = items.Select(x => x.Title.Length).Max();
var result =
String.Join(Environment.NewLine,
items.Select(x =>
String.Format(
"Record[{0}]{1} Title : {2}{3} Date : {4:dd/MM/yy}",
x.Record,
"".PadLeft(paddingRecord - x.Record.ToString().Length),
x.Title,
"".PadLeft(paddingTitle - x.Title.Length),
x.Date)));
I get this for result:
Record[1] Title : Foo Date : 23/05/14
Record[1000] Title : Foo Bar Date : 23/05/14

Related

Replace any index in a text frame with output of a method

I design a frame for message with a some index in it for each person in list. like the one bellow:
Dear {0}
Hi,
the total amount of Draft is {1}.
amount of prm is {2}
yesterday amount is {3}
I wrote a method witch return all different type of amount and insert the out put of method in a list . I want to replace each item of text frame with the correct amount .
for example the output like the list bellow :
sale
reject amount
damage amount
1230
56555
79646354
my method like bellow :
public List<outputList1> listAmount()
{
var amounts = (from p in db.FactTotalAmount
group p by p.FromDate into g
select new outputList1
{
YesterdaySalesPrm = g.Sum(x =>
x.YesterdaySalesPrm),
YesterdayDraftAmount = g.Sum(x =>
x.YesterdayDraftAmount),
PrmSales = g.Sum(x => x.PrmSales),
DraftAmount = g.Sum(x => x.DraftAmount)
}).ToList();
return amounts;
}
would you please help me what should I do
I'm going to teach you to fish.
There are two main ways to build a string using a template - formatting and interpolation.
Option one: use string.Format:
string output = string.Format("Today is {0}. Weather is {1} at {2}°.", "Monday", "rain", 75.2);
// result is "Today is Monday. Weather is rain at 75.2°."
Option two: use C# 6 string interpolation:
string dayOfWeek = "Monday";
string weather = "rain";
decimal temp = 75.2;
// Notice the "$" at the start of the string literal
string output = $"Today is {dayOfWeek}. Weather is {weather} at {temp}°.";
So, you have a model - the data you've collected - and a format string. Combine those together with one of these options to produce the final output string.

Split CSV and concat suffix from multiple properties into a list

I have three string properties that are formatted as CSV:
string Tap70V = "1,2,3,4" //example data
string Tap100V = "10,20,30,40" //example data
string Tap25V = ".2,.4,.6,.8" //example data
I want the following result in a List so I can bind it to a Combobox:
".2 Watt 25V"
".4 Watt 25V"
".6 Watt 25V"
".8 Watt 25V"
"1 Watt 70V"
"2 Watt 70V"
"3 Watt 70V"
and so on until it shows
"4 Watt 100V"
I know I need to union the three properties together, split them by "," into a list then concatenate the suffix "Watt XXV". (not necessarily in that order)
I just can't figure out a good one or two line way to do this
First, you should move the values of your variables into a dictionary structure like below
var tbl = new Dictionary<string, string>() {
{ "70V", "1,2,3,4" },
{ "100V", "10,20,30,40" },
{ "25V", ".2,.4,.6,.8" },
};
Then you can easily query it out using the below code
tbl.SelectMany(x => x.Value.Split(',').Select(y => $"{y} Watt {x.Key}"));
The SelectMany call flattens the multi-level hierarchy, and returns an IEnumerable<string> with the required string. The $"{y}" syntax if for an interpolated string, if you don't use a supported version of C#, then you can use a string.Format instead of string interpolation
UPDATE
Based on the OP's comment, I am providing a way to form the dictionary above
var tbl = new Dictionary<string, string>() {
{ nameof(Tap70V), Tap70V },
{ nameof(Tap100V), Tap100V },
{ nameof(Tap25V), Tap25V },
};
By relying on variable names for values is a dangerous practice. If the OP provides, how the value of 70V, 100V and 25V are available, then I can update the answer with a suitable way to adapt that to this solution
Here is the cleanest way I could figure out to accomplish my question:
if (value is IItemLibrarySpeaker s)
{
List<string> taps = s.Speaker25VTaps.Split(',').Select(x => $"{x} Watt/25V").ToList();
taps.AddRange(s.Speaker70VTaps.Split(',').Select(x => $"{x} Watt/70V"));
taps.AddRange(s.Speaker100VTaps.Split(',').Select(x => $"{x} Watt/100V"));
return taps;
}
Thanks for the suggestions (even the ones that had nothing to do with my question)
As per provided sample data i made sample code as below:
string Tap70V = "1,2,3,4"; //example data
string Tap100V = "10,20,30,40"; //example data
string Tap25V = ".2,.4,.6,.8"; //example data
var test = new List<string>();
test.AddRange(Tap70V.Split(',').Select(val => val + " Watt 70V"));
test.AddRange(Tap100V.Split(',').Select(val => val + " Watt 100V"));
test.AddRange(Tap25V.Split(',').Select(val => val + " Watt 25V"));
In above piece of code, add string objects value into List<string> variable named test.
For every object data need to split and AddRange into List.
The problem is: how do you know that the range of values have something to do with 70V and the range of values have something to do with 25V?
But let's assume you have a sequence of Voltage Text combinations:
Voltage | Text
70 | "1,2,3,4"
100 | "10,20,30,40"
25 | ".2,.4,.6,.8"
For instance, to create them from your three variables:
IEnumerable<VoltageTextCombination> voltageTextCombinations = new VoltageTextCombination[]
{
new VoltageTextCombination {Voltage = 70, Text = Tap70V},
new VoltageTextCombination {Voltage = 100, Text = Tap100V},
new VoltageTextCombination {Voltage = 25, Text = Tap25V},
}
I defined a class VoltageTextCombination for this. Of course you could also use an anonymous type for this.
To get your sequence of combo box items, you need to split the Text into a sequence of Watts, and use the correct SelectMany overloads to get a sequence of Voltage - Watt combinations. After that you use String.Format to convert every Voltage - Watt combination into the text that you want to display:
Constants used in the LINQ below, used to split your input text into Watts, and to format the Voltage - Watt combinations into a string:
static readonly char[] separatorChars = new char[] {','};
const string strFormat ="{0} Watt {1}V";
The LINQ query:
var result = voltageTextCombinations.SelectMany(
// parameter collectionSelector:
// input a source element (= one voltageTextCombination)
// output a sequence (= the text of the combination split into Watts
combination => combination.Text.Split(separatorChars),
// parameter resultSelector: take one source element, and one of every watt
// to make a Voltage - Watt combination
(voltageTextCombi, splitString) => new
{
Voltage = voltageTextCombi.Voltage,
Watt = splitString,
})
// convert every Voltage-Watt combination to one string:
.Select(voltageWattCombi => String.Format(strFormat,
voltageWattCombi.Watt,
voltageWattCombi.Voltage));
Simple comme bonjour!

Format DataGridView TextBox Column Containing Numeric Values

I have a DataGridView with TextBox colums. One of the columns display record counts which are formatted as ###,###,000. The column itself isn't set to format the text, but the data is formatted when the data source is populated. The data source is a List by the way. The DataGridView merely displays everything as it gets it.
Now, I need to parse the numeric text value into a variable, which is fine by doing
int.Parse(data_grid_view_row.Cells["col_Record_Count"].Value.ToString())
but, if I have numbers reaching thousands, it displays as 1 000, because of the formatting. The formatting generates a space rather than a comma as this is how the environment has been configured. When I try to parse that value, I get an exception because of the space in the numeric value.
I have tried formatting the string value
int.Parse(String.Format("{0:000000000}", data_grid_view_row.Cells["col_Record_Count"].Value.ToString()))
and
int.Parse(String.Format("{0:########0}", data_grid_view_row.Cells["col_Record_Count"].Value.ToString()))
and all sorts of variants, but it keeps returning the space in the value, which then won't parse. I have tried replacing the space, but it is persistent. Also, the space shows ASCII keycode 63 which is supposed to be a question mark, not so? Even when I try to replace using the keycode... nothing!
Any ideas as to why this is happening and how to fix it?
The complete code block I have is
foreach (DataGridViewRow data_grid_view_row in dgv_Migration_Files.Rows)
{
if ((bool)data_grid_view_row.Cells["col_Select"].Value == true)
{
//-------------------------------------------------------------------------
// this is only to test and see what value I get for the space character, will be removed later
string test_str = data_grid_view_row.Cells["col_Record_Count"].Value.ToString().Replace(" ", string.Empty);
test_str = test_str.Replace(" ", "");
for (int k = 0; k < test_str.Length; k++)
{
string newstr = test_str.Substring(k, 1);
var kycode = ASCIIEncoding.ASCII.GetBytes(newstr);
}
//-------------------------------------------------------------------------
migrate.Add(new Migrate()
{
File_Folder = data_grid_view_row.Cells["col_File_Folder"].Value.ToString()
,
File_Name = data_grid_view_row.Cells["col_File_Name"].Value.ToString()
,
Record_Count = int.Parse(String.Format("{0:000000000}", data_grid_view_row.Cells["col_Record_Count"].Value.ToString()))
});
}
}
Use simple Solution:-
If space is available Remove it and then simply Parse into INT.
str.Replace(" ", String.Empty)
string data = data_grid_view_row.Cells["col_Record_Count"].Value.ToString().Replace(" ", String.Empty);
int.Parse(data);
Make it easier:-
int.Parse(data_grid_view_row.Cells["col_Record_Count"].Value.ToString().replace(" ", String.Empty));
And if you want to remove space and comma both while parsing using this Regular Expression
int.Parse(data_grid_view_row.Cells["col_Record_Count"].Value.ToString().replace(/[, ]+/g, " ").trim());
Check This Small Example First you will get Clear Idea:-
string data = "1 0000";
string result = data.Replace(" ", string.Empty);
Since the replace method didn't remove spaces as I expected to, I resorted to the below solution. This will also remove any other numeric separators irrespective of what the numeric separator has been set up as in the OS.
//get the numeric decimal seperator key code
string dummy_numeric = (1000).ToString(Helper.application_number_display_format);
char replace_char = (char)0;
foreach (char current_char in dummy_numeric)
{
if (!System.Char.IsDigit(current_char))
{
replace_char = current_char;
break;
}
}
//get all the files that are selected for migration
List<Migrate> migrate = new List<Migrate>();
foreach (DataGridViewRow data_grid_view_row in dgv_Migration_Files.Rows)
{
if ((bool)data_grid_view_row.Cells["col_Select"].Value == true)
{
migrate.Add(new Migrate()
{
File_Folder = data_grid_view_row.Cells["col_File_Folder"].Value.ToString()
,
File_Name = data_grid_view_row.Cells["col_File_Name"].Value.ToString()
,
Record_Count = int.Parse(data_grid_view_row.Cells["col_Record_Count"].Value.ToString().Replace(replace_char.ToString(), ""))
});
}
}

How to format my output of List of arrays c#

I have a nested foreach loop. I want to display the results like this:
TIME - TITLE - DESCRIPTION
TIME2 - TITLE2 - DESCRIPTION2
The loop:
foreach (string[] array in log)
{
foreach (string element in array)
{
Console.WriteLine(element);
}
}
But currently the result is like this:
TIME
TITLE
DESCRIPTION
How can I format this the arrays in my List goes on the same line? And when the first array it goes on the second line and so forth?
In order to output your strings in the manner you've asked for you need to know how much padding to add to each string to ensure that the - characters line up. The first column, in your sample text, has a maximum of 5 characters, so the first column in the first line needs to have an extra space added to make the - character line up before the second column starts, etc.
So, first you need to work out the max_lengths of each column:
var max_lengths =
log
.SelectMany(array =>
array.Select((e, i) => new { length = e.Length, index = i }))
.GroupBy(x => x.index, x => x.length)
.Select(x => new { index = x.Key, max_length = x.Max() })
.ToDictionary(x => x.index, x => x.max_length);
That gives:
Now you can create a version of log that has the padded strings:
var padded =
log.Select(array =>
array.Select((e, i) => e.PadRight(max_lengths[i])));
Now the result is simply this:
var result = String.Join(Environment.NewLine, padded.Select(x => String.Join(" - ", x)));
Which is:
TIME - TITLE - DESCRIPTION
TIME2 - TITLE2 - DESCRIPTION2
We can test this with a more interesting set of inputs:
var log = new []
{
new [] { "TIME", "TITLE", "DESCRIPTION" },
new [] { "Happy Days", "Super Fun", "Woah!" },
new [] { "Yes", "I can't complain", "simply stunning" },
};
That gives:
TIME - TITLE - DESCRIPTION
Happy Days - Super Fun - Woah!
Yes - I can't complain - simply stunning
Append values in a string in any format you want to and then display that string.
For e.g
String s = s + element;
Console.WriteLine(s);
With Console.Write(element + " - "); you can write various elements in one line. After every element there is a " - " so they are seperated.
In the outer loop you want to have Console.WriteLine(); to break to a new Line for your next elements.
Only Problem with this: You will have " - " at the end of your elements. Looking like:
TIME - TITLE - DESCRIPTION -
Thanks to #Roma
You could edit your loop like this:
foreach (string[] array in log)
{
foreach (string element in array)
{
Console.Write(element + " - ");
}
Console.WriteLine();
}
The Output should look like:
TIME - TITLE - DESCRIPTION -
TIME2 - TITLE2 - DESCRIPTION2 -
A very simple apporach is joining the string:
Console.WriteLine(string.Join(" - ", array));
The result is exactly a string like TIME - TITLE - DESCRIPTION you expected.
Lets say that array list like :
List<string[]> arrayList = new List<string[]>
{
new string[] { "TIME1", "TITLE1" ,"DESCRIPTION1"},
new string[] { "TIME2", "TITLE2" ,"DESCRIPTION2" }
};
then foreach loop will be like :
foreach (string[] array in arrayList)
{
Console.WriteLine(array[0] + " - " + array[1] + " - "+ array[2]);
}
output
TIME1 - TITLE1 - DESCRIPTION1
TIME2 - TITLE2 - DESCRIPTION2

C# Equal Tab Spacing

So I have a C# program that collects a list of customers. The list displays Customer ID, Customer Name, and Customer Phone Number. The list is shown in a multi-line text box. My issue is, a customer is allowed to either use first and last name, or first middle and last name, and when the list is displayed, if one of the customers only put a first and last name, the phone number is literally right next to the name instead of tabbed like the others. I will demonstrate what I mean below.
Notice how Bob Anthony's phone number is off compared to Mary and John? What would I use to make sure that every line has the same space in the tabs?
While some type of a data grid or list view would probably be more appropriate, if you want to keep it in string form you can use some of the composite formatting features in String.Format - notably the alignment flag:
string.Format("{0,-8} {1,-20} {2}", stuff)
The negative/positive indicates left/right alignment. Note that strings aren't truncated for you, you'll have to do that if you don't already know the max width.
You should get length of the longest item and add space after other items so that all of them be equal. By the way, I suggest you to use DataGridView for your application. Something like this:
dataGridView1.Rows.Add(3);
dataGridView1.Rows[0].Cells[0].Value = customer.ID;
dataGridView1.Rows[0].Cells[1].Value = customer.Name;
dataGridView1.Rows[0].Cells[2].Value = customer.Phone;
As everyone has said a DataGridView is recomendable and easy to use, instead of truncating the information or padding it the user can resize the columns. If you still want to do it that way then you have to get each customer and format it accordingly:
var text = new StringBuilder();
foreach (var customer in Customers)
{
var format = String.Format("{0} {1} {2}\n",
FormatField(customer.Id,6),
FormatField(customer.Name,20),
FormatField(customer.Phone,10) // Might need extra formating
);
text.Append(format);
}
And to format it:
private string FormatField(object field, int size)
{
var value = field.ToString();
if (value.Length == size)
return value;
return value.Length > size
? value.Substring(0,size)
: value.PadRight(size, ' ');
}
Depending on where you display it you will see some inconsistencies, like its not the same "view width" the characters "iii" and "MMM" even that they have the same length.

Categories