How to add strings and show as a full sentence - c#

I've assigned some string values from a data set to the string b.
for (int i = 0; i <= ds.Tables[0].Rows.Count - 1; i++)
{
string b = ds.Tables[0].Rows[i].ItemArray[0] + " " + ds.Tables[0].Rows[i].ItemArray[1];
}
What I want to do is add those values, and finally show as a sentence.
Example: if "dog", "cat", and "cow" are the values read by the for loop, I want to display "dog cat cow" in a message box. How to do that?

Edit: Since it appears you are interested in the String.Join() method this could work perfectly for you. You have plenty of options here but if you want to go that route here's how.
First create an array of the items you are returning then you can simple use the String.Join() method to concatenate the items in the array like so:
string separator = whatever seperator you want "," or "|"
string d = String.Join(separator, animalArray);
MessageBox.Show(d);
The first thing you'll need to do is make sure you have imported the System.Windows.Forms namespace to enable your ability to call the MessageBox function.
Essentially you are already there with the concatenation of the strings. If you are looking for a cleaner option I would recommend using String.Format() or using the newer method of concatenation by applying a '$' character in front of a string which allows you to simple add your variables between curly braces.
For example: $"Hello my name is {name}."

What's wrong with the above?
You already have them in your string variable b.
Enclose it in MessageBox.Show(); instead of adding the variable.
string b = "";
for (int i = 0; i <= ds.Tables[0].Rows.Count - 1; i++)
{
b += ds.Tables[0].Rows[i].ItemArray[0] + " " + ds.Tables[0].Rows[i].ItemArray[1] + "\n";
}
MessageBox.Show(b);

Related

Sorting a given string - What is wrong with my IF Contains block?

Super new to C# apologize upfront. My goal is to sort a given string. Each word in the string will contain a single number. This number is the position the word should have in the result. Numbers can be from 1 to 9. So 1 will be the first word (not 0).
My plan of attack is to split the string, having one variable of int data-type (int lookingForNum) and the other variable turning that into a String data-type(string stringLookingForNum), then for each loop over the array looking to see if any elements contain string stringLookingForNum, if they do I add it to an emptry string variable, lastly add 1 to int variable lookingForNum. My issue seems to be with the if statement with the Contains method. It will not trigger the way I currently have it written. Hard coding in if (word.Contains("1")) will trigger that code block but running it as written below will not trigger the if statement.Please can anyone tell my WHY!?!? I console.log stringLookingForNum and it is for sure a string data type "1"
This noobie would appreciate any help. Thanks!
string testA = "is2 Thi1s T4est 3a"; //--> "Thi1s is2 3a T4est"
string[] arrayTestA = testA.Split(' ');
string finalString = string.Empty;
int lookingForNum = 1; //Int32
foreach (string word in arrayTestA){
string stringLookingForNum = lookingForNum.ToString();
//Don't understand why Contains is not working as expected here)
if (word.Contains(stringLookingForNum)){
finalString = finalString + $"{word} ";
}
lookingForNum++;
}
you need this - look for the string with 1, the look for the string with 2 etc. Thats not what you are doing
you look at the first string and see if it contains one
then look at the second one and see if it contains 2
....
int lookingForNum = 1;
while(true){ // till the end
string stringLookingForNum = lookingForNum.ToString();
bool found = false;
foreach (string word in arrayTestA){
if (word.Contains(stringLookingForNum)){
finalString = finalString + $"{word} ";
found = true;
break;
}
}
if(!found) break;
lookingForNum++;
}
To sort you should simply use OrderBy, and since you need to sort by number inside a word - just Find and extract a number from a string
string testA = "is2 Thi1s T4est 3a";
var result = testA.Split().OrderBy(word =>
Int32.Parse(Regex.Match(word, #"\d+").Value));
Console.WriteLine(string.Join(" ", result));

Can I shorten this code with a loop in C#?

I have this code written in C# but looks kind of "bad" and I would like to shorten it somehow and keep it clean and simple.
All this code works pretty fine but I want to know if there's any other way I can achieve the same thing.
EDIT: I forgot to mention that the firstLine has a bad date format attached with it, so it is like this: "This_is_my_first_line_20220126". So I split the string and then only join it with the corrected date. The problem is that I can never know how long the new string would be and I don't want to handle the code like this and go up to 100 parts.
Here's my code:
string correctDate = "26012022";
string[] lines = File.ReadAllLines("text.txt");
string firstLine = lines.FirstOrDefault();
//note: firstLine looks like this: This_is_my_first_line_20220126
string[] sub = firstLine.Split('_');
string name="";
if(sub.Length==2)
name = sub[0]+"_"+sub[1]+"_"+correctDate;
else if(sub.Length==3)
name = sub[0]+"_"+sub[1]+"_"+sub[2]+"_"correctDate;
...
else if(sub.Length==20)
name = sub[0]+"_"+ ... "_" + sub[19];
Now, my final name value should be "This_is_my_line_26012022" but I want it to depend on the length of the given string. So far I know that the maximum length would go up to 20 but I don't want my code to look like this. Can I shorten it somehow?
you can find the LastIndexOf the underscore and drop the date by using Substring:
string firstLine = "This_is_my_first_line_20220126";
string correctDate = "26012022";
string correctString = firstLine.Substring(0, firstLine.LastIndexOf("_") + 1) + correctDate;
Still a little perplexed with the split aproach, but this a way to join back all elements
string name = string.Join("_", sub.Take(sub.Length - 1).Append(correctDate));
Or use the substring method (and no need of all that split & join)
name = firstLine.Substring(0, firstLine.LastIndexOf("_") +1) + correctDate;
I forgot to mention that firstLine has a bad date format like "This_is_my_Line_20220125"
If you want to correct just the first line:
string correctDate = "26012022";
string[] lines = File.ReadAllLines("text.txt");
lines[0] = lines[0][..^8] + correctDate;
[..^8] uses C# 9's "indices and ranges" feature, that allows for a more compact way of taking a substring. It means "from the start of the string, up to the index 8 back from the end of the string".
If you get a wiggly line and possibly a messages like "... is not available in C# version X" you can use the older syntax, which would be more like lines[0] = lines[0].Remove(lines[0].Length - 8) + correctDate;
If you want to correct all lines:
string correctDate = "26012022";
string[] lines = File.ReadAllLines("text.txt");
for(int x = 0; x < lines.Length; x++)
lines[x] = lines[x][..^8] + correctDate;
If the incorrect date isn't always 8 characters long, you can use LastIndexOf('_') to locate the last _, and snip it to that point

getting current line text is on

I have a list of lines that looks like this:
textbox.text += "p"+b+" the rest\r\np"+b+" more text";
b is supposed to represent the current line number in the textbox that the line is on. I have tried using textbox.lines.count() but it only changes i into the last line number.
Is there any other way about going with this, or do I have to switch to another method?
If you are assigning, I think you can do it manually (calculate the line number). There is no function that could "guess" on which line the tex will appear.
You can create a integer variable and increment it when appending a line/s and use the variable when you need to display the current line number.
I split the lines by the line breaks ("\r\n") and used a for loop to replace "b" (I changed it to string rather than a variable)
for (int i = 0; i < da.Length; i++)
{
//replace char with number
string f = da[i].Replace("n", (i + 1).ToString());
disp.Text += f + "v";
}
I added "v" so that I can replace it outside of the loop with "\r\n" again.

How does the C# compiler work with a split?

I have an List<string> that I am iterating through and splitting on each item then adding it to a StringBuilder.
foreach(string part in List)
{
StringBuilder.Append(part.Split(':')[1] + " ");
}
So my question is how many strings are created by doing this split? All of the splits are going to produce two items. So... I was thinking that it will create a string[2] and then an empty string. But, does it then create the concatenation of the string[1] + " " and then add it to the StringBuilder or is this optimized?
The code is actually equivalent to this:
foreach(string part in myList)
{
sb.Append(string.Concat(part.Split(':')[1], " "));
}
So yes, an additional string, representing the concatenation of the second part of the split and the empty string will be created.
Including the original string, you also have the two created by the call to Split(), and a reference to the literal string " ", which will be loaded from the assembly metadata.
You can save yourself the call to Concat() by just Appending the split result and the empty string sequentially:
sb.Append(part.Split(':')[1]).Append(" ");
Note that if you are only using string literals, then the compiler will make one optimzation for you:
sb.Append("This is " + "one string");
is actually compiled to
sb.Append("This is one string");
3 extra strings for every item
part[0];
part[1];
part[1] + " "
the least allocations possible would be to avoid all the temporary allocations completely, but the usual micro-optimization caveats apply.
var start = part.IndexOf(':') + 1;
stringbuilder.Append(part, start, part.Length-start).Append(' ');
You have the original string 'split' - 1 string
You have the 'split' split into two - 2 string
You have the two parts of split joined - 1 string
The string builder does not create a new string.
The current code uses 4 strings, including the original.
If you want to save one string do:
StringBuilder.Append(part.Split(':')[1]);
StringBuilder.Append(" ");
This code:
foreach(string part in List)
{
StringBuilder.Append(part.Split(':')[1] + " ");
}
Is equivalent to:
foreach(string part in List)
{
string tmp = string.Concat(part.Split(':')[1], " ");
StringBuilder.Append(tmp);
}
So yes, it's creating a string needlessly. This would be better, at least in terms of the number of strings generated:
foreach(string part in List)
{
StringBuilder.Append(part.Split(':')[1])
.Append(" ");
}
So for each value in the list (n, known as part in your code) you are allocating:
x (I assume 2) strings for the split.
n strings for the concatenation.
Roughly n + 1 string for the StringBuilder; probably much less though.
So you have nx + n + n + 1 at the end, and assuming the split always results in two values 4n + 1.
One way to improve this would be:
foreach(string part in List)
{
var val = part.Split(':')[1];
StringBuilder.EnsureCapacity(StringBuilder.Length + val.Length + 1);
StringBuilder.Append(val);
StringBuilder.Append(' ');
}
This makes it 3n + 1. It is a rough estimate as StringBuilder allocates strings as it runs out of space - but if you EnsureCapacity you will prevent it from getting it wrong.
Probably the only way to be sure about how this is compiled is to build it and decompile it again with Refactor to see how it's internally handled. Anyway have in mind that probably it does not have impact on the whole app performance.

How can i trim or remove " , " at the end of my query?

i try to write a query but my query finished with "Control nvarchar(500), ". i want to finish "Control nvarchar(500)" How can remove ",", " "?
void SqlTable(List listMyColumnNames, string TableName)
{
string Text = "Create table ENG_"+TableName+" (ENG_"+TableName+"_ID integer PRIMARY KEY identity(1,1), ";
char[] MyChar = {',', ' ' };
for (int i = 0; i < listMyColumnNames.Count; )
{
Text+=listMyColumnNames[i]+" nvarchar(500), ";
if (i == listMyColumnNames.Count-1)
Text.TrimEnd(MyChar);
i++;
}
Text+=" )";
I think you may want to look at String.Join. What you can do is transform your column name strings, containing the SQL definition of your colum, e.g. MyColumnName[1]+" nvarchar(500)", into alistMyColumnDefarray, thenJoin` that array with the comma as a separator.
The benefit:
no 'if I'm the last entry',
clear separation of your column names and your SQL representation for a column
The drawbacks.... none :)
for( String name in listMyColumnNames ) {
listMyColumnDefs.Add( name + " nvarchar(500)" );
}
String mycolumndef = String.Join( listMyColumnDefs, ", ");
There are many ways to fix this, but here's the problem in your code:
if (i == listMyColumnNames.Count-1)
Text.TrimEnd(MyChar); // doesn't work like this!
String is immutable: you can't invoke a method on it and expect it to be mutated by the method. TrimEnd instead returns a new String, so what you need to do is:
Text = Text.TrimEnd(MyChar); // now works fine!
Related questions
Why string.Replace(“X”,“Y”) works only when assigned to new string?
for (int i = 0; i < listMyColumnNames.Count; ++i)
{
Text += listMyColumnNames[i] + " nvarchar(500)";
if (i < listMyColumnNames.Count-1)
Text += ", ";
}
Or you could just remove your Trim call and add `Text = Text.Replace(", )", " )");' at very end.
Have you thought about using the StringBuilder object to build your string, rather than concatenating yours string in a loop!
http://www.yoda.arachsys.com/csharp/stringbuilder.html

Categories

Resources