StringBuilder formatting with list - c#

I am having problems formatting a list with stringbuilder to output the way I need it. Basically need my list to drop a line every two values. For example I loop through a series of text boxes and add entered text to the list. I then loop through the list and print or copy to clipboard the data:
List<string> listValues = new List<string>();
StringBuilder value = new StringBuilder();
foreach (TextBox x in controlGrid.Children.OfType<TextBox>())
{
if (x.Text.Length > 0)
{
listValues.Add(x.Text);
}
}
for (int i = 0; i < listValues.Count; i++)
{
// formating code w/ listValues[i];
}
I need it to format as such:
listValues[0] + " " + listValues[1]
listValues[2] + " " + listValues[3]
listValues[4] + " " + listValues[5]
which to the user would paste like:
1 foo
2 fooa
3 foob
I have searched around for a good bit and can't find a similar result so if the easy answer is out there I apologize for the repeat.
Thanks

Do you even need the list? Just go straight into the StringBuilder like this?
bool first = true;
StringBuilder value = new StringBuilder();
foreach (TextBox x in controlGrid.Children.OfType<TextBox>())
{
if (x.Text.Length > 0)
{
value.Append(first ? x.Text : " " + x.Text + "\r\n");
first = !first;
}
}
Console.WriteLine(value.ToString());

You could use LINQ for the purpose.
var result = listValues.Select((x, i) => new { Index = i, Value = x })
.GroupBy(x => x.Index / 2)
.Select(x => string.Join(" ", x.Select(c => c.Value)));
Sample Input
1
Foo
2
fooa
3
foob
Output
1 Foo
2 fooa
3 foob

Related

Checking last element in string and removing c#

I have a list of strings that I am wanting to remove the , from the end of the string. I looked up online how to check to see if you are at the last index of a string and on how to remove the last index from the string. But when I do the following, it still does not seem to remove the ,.
List<string> groceryList = "apple, fruit, banana, carrots, mango";
var x = "buy ";
var y = groceryList;
foreach (var item in y)
{
x = x + item + ", ";
if (item == y.Last()){
x.Remove(x.Length - 1); }
}
I even tried x.Remove(x.Length - 2) thinking it would hit the , but the variable x still contains the , at the end of the string. Also I tried x.Remove(x.Last()) but it still does not remove the , after mango. So it will show mango, instead of mango.
You have to reassign the value of the x. The following code should give you the desired result.
x = x.Remove(x.Length - 2, 2);
You're better off avoiding the dangling comma in the first place.
Try this:
List<string> groceryList = new List<string>() { "apple", "fruit", "banana", "carrots", "mango" };
string x = $"buy {String.Join(", ", groceryList)}";
That gives me buy apple, fruit, banana, carrots, mango.
If you want to build it yourself, then an for loop is the way to go:
for (int i = 0; i < groceryList.Count; i++)
{
x += groceryList[i];
if (i < groceryList.Count - 1)
x += ", ";
}
Or an enumerator:
var e = groceryList.GetEnumerator();
if (e.MoveNext())
{
while (true)
{
x += e.Current;
if (e.MoveNext())
x += ", ";
else
break;
}
}

String substitution in C#

I have a list of names and I loop through them to create a comma separated list in a string variable (Bob, George, Will, Terry).
I need the list to eventually look like (Bob, George, Will and Terry).
How do I find the LAST instance of the comma and replace it with the word "and"? Once I find the LAST instance, I think it's a simple matter of doing something like
string new=ori.Substring(0,start) + rep + ori.Substring(start+rep.Length);
Thoughts? Comments? Suggestions?
Thanks,
Bob
This should work for you. Added the alternative comma style as well.
var names = "Bob, George, Will, Terry";
var lastCommaPosition = names.LastIndexOf(',');
if (lastCommaPosition != -1)
{
names = names.Remove(lastCommaPosition, 1)
//.Insert(lastComma, " and");
.Insert(lastCommaPosition, ", and");
}
Console.WriteLine(names);
You can use a combination of LINQ and String.Join. This solution does not need the last index of a comma and is "more fluent" to read.
var list = new List<string> { "Bob", "George", "Will", "Terry" };
var listAsString = list.Count > 1
? string.Join(", ", list.Take(list.Count - 1)) + " and " + list.Last()
: list.First();
You can use Linq,
list.Select(i => i).Aggregate((i, j) => i + (list.IndexOf(j) == list.Count -1 ? " and " : " , ") + j);
Hope helps,
This should do the trick for you:
var foo = "Bob, George, Will, Terry";
if (foo.Contains(",")) {
foo = foo.Substring(0, foo.LastIndexOf(",")) + " and" + foo.Substring(foo.LastIndexOf(",")+ 1);
}
I'm not sure what you wanted to do, but the following code works:
string original = "(Bob, George, Will, Terry)";
string result = "";
string[] splited = original.Split(',');
for (int i = 0; i < splited.Count(); i++)
{
if(i == splited.Count() - 2)
{
result += splited[i] + " and";
}
else if(i == splited.Count() - 1)
{
result += splited[i];
}
else
{
result += splited[i] + ",";
}
}
I Used split to split the original string in a vector so i worked with this vector to replace the last comma to the word "and".

Using Substring to find occurrence number

I am reading a file in C#. I want to check value from a string. The line consists as following:
20 EMP HAPPENS 5 TIMES.
40 SUP HAPPENS 7 TIMES.
I want to find the number of times. I have written the following code:
if(line.IndexOf(HAPPENS) + 1 > 0)
arrayLength= int.Parse(line.Substring(line.IndexOf(HAPPENED) + OCCURS.Length + 1).Trim("."));
But exception is thrown.
What is the efficient way to do that?
Substring method takes two params, see declaration:
public string Substring(int startIndex,int length)
Here some psuedo code to get your count:
//read lines from file
foreach (string line in lines){
if (line.Contains("HAPPENS")){
int happensindex = line.IndexOf("HAPPENS");
int timesindex = line.IndexOf("TIMES");
int happenscount;
int indexCount = happensindex + 8;
int countLength = happensindex - timesindex - 9;
if (int.TryParse(line.Substring(indexCount , countLength), out happenscount){
//happenscount contains your count
}
}
}
You can use this LINQ query to real the lines of the file and extract the informations:
var allOccurrences = File.ReadLines("Path")
.Select(l => new { HappenIndex = l.IndexOf(" HAPPENS "), Line = l })
.Where(LineInfo => LineInfo.HappenIndex >= 0)
.Select(LineInfo =>
{
var retVal = new { LineInfo, What = LineInfo.Line.Substring(0, LineInfo.HappenIndex).Trim(), Occurences = (int?)null };
int timesIndex = LineInfo.Line.IndexOf(" TIMES", LineInfo.HappenIndex + " HAPPENS ".Length);
if(timesIndex >= 0)
{
int behindHappen = LineInfo.HappenIndex + " HAPPENS ".Length;
string times = LineInfo.Line.Substring(behindHappen, timesIndex - behindHappen).Trim();
int occurences;
if(int.TryParse(times, out occurences))
retVal = new { LineInfo, retVal.What, Occurences = (int?)occurences };
}
return retVal;
})
.Where(x => x.Occurences.HasValue)
.ToList();
foreach (var occ in allOccurrences)
{
Console.WriteLine("Line contains '{0}' {1} times", occ.What, occ.Occurences);
}

Listbox character limit per line

I have a listbox in my windows form application that shows quite long texts. Since texts are so long, user have to use the horizontal slider for check the rest of text.
So, I want to limit listbox character per line. For every 50 char it should go to next row, so user won't have to use glider.
I can't put "new line" since text source is Sql Database.
My code is basically this:
listbox1.items.add(dbRead["LongText"]); // dbRead = SqlDataReader
So I have to edit listbox itself. I've checked it a bit, but didn't manage to find. I've also tried to find an event like when text is changed, for every 50 char listbox.items.add("") etc. I'm still alien to syntax.
Any suggestions ?
You can write an extension method(SplitByLength) like below
var input = "I have a listbox in my windows form application that shows quite long texts. Since texts are so long, user have to use the horizontal slider for check the rest of text.\nSo, I want to limit listbox character per line. For every 50 char it should go to next row, so user won't have to use glider.";
var lines = input.SplitByLength(50).ToArray();
listBox1.Items.AddRange(lines);
public static partial class MyExtensions
{
public static IEnumerable<string> SplitByLength(this string input, int maxLen)
{
return Regex.Split(input, #"(.{1," + maxLen + #"})(?:\s|$)")
.Where(x => x.Length > 0)
.Select(x => x.Trim());
}
}
----------EDIT----------
After tinstaafl's comment, an edit seems to be a must
var input = "I have a listbox in my windows form application that shows quite long texts. Since texts are so long, user have to use the horizontal slider for check the rest of text.\nSo, I want to limit listbox character per line. For every 50 char it should go to next row, so user won't have to use glider.";
input = String.Join(" ", Enumerable.Repeat(input, 100));
var t1 = Measure(10, () =>
{
var lines = input.SplitByLength_LB(50).ToArray();
});
var t2 = Measure(10, ()=>
{
var lines = input.SplitByLength_tinstaafl(50).ToArray();
});
long Measure(int n,Action action)
{
action(); //JIT???
var sw = Stopwatch.StartNew();
for (int i = 0; i < n; i++)
{
action();
}
return sw.ElapsedMilliseconds;
}
public static partial class MyExtensions
{
public static IEnumerable<string> SplitByLength_LB(this string input, int maxLen)
{
return Regex.Split(input, #"(.{1," + maxLen + #"})(?:\s|$)")
.Where(x => x.Length > 0)
.Select(x => x.Trim());
}
public static IEnumerable<string> SplitByLength_tinstaafl(this string input, int maxLen)
{
List<string> output = new List<string>();
while (input.Length > 0)
{
output.Add(new string(input.Take(maxLen).ToArray()));
input = new string(input.Skip(maxLen).ToArray());
}
return output;
}
}
And my results are different than yours: 11 ms. vs. 3384 ms. :)
Redid my code to take into account spaces. With variable length lines some shorter some longer than 50 characters and the line breaks adjusted for spaces, I found that the performance is very close to the same. They're both between 15 and 25 milliseconds on 1000 strings. Though regex does perform moderately faster. Here's the code I used:
public static partial class MyExtensions
{
public static IEnumerable<string> SplitByLength_LB(this string input, int maxLen)
{
return Regex.Split(input, #"(.{1," + maxLen + #"})(?:\s|$)")
.Where(x => x.Length > 0)
.Select(x => x.Trim());
}
public static IEnumerable<string> SplitByLength_tinstaafl(this string input, int maxLen)
{
List<string> output = new List<string>{""};
string[] temp = input.Split("\n ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
for(int i = 0; i < temp.Count(); i++)
{
if((output.Last() + " " + temp[i]).Length > 50)
{
output.Add(temp[i]);
}
else
output[output.Count() - 1] += " " + temp[i];
}
return output;
}
return output;
}
The test is like this:
Stopwatch s1 = new Stopwatch();
List<string> source = new List<string>();
Random rnd = new Random();
for(int i = 0; i < 1000; i++)
{
var input = "I have a listbox in my windows form application that shows quite long texts. Since texts are so long, user have to use the horizontal slider for check the rest of text. So, I want to limit listbox character per line.";
int nextbreak = rnd.Next(20, input.Length);
source.Add(new string(input.TakeWhile((x, y) => input.IndexOf(' ', y) <= nextbreak).ToArray()));
}
s1.Start();
List<string> output = new List<string>(from s in source
from p in s.SplitByLength_LB(50)
select p);
s1.Stop();
Console.WriteLine("SplitByLength_LB\t" + s1.ElapsedMilliseconds.ToString());
s1.Reset();
s1.Start();
List<string> output2 = new List<string>(from s in source
from p in s.SplitByLength_tinstaafl(50)
select p);
s1.Stop();
Console.WriteLine("SplitByLength_tinstaafl\t" + s1.ElapsedMilliseconds.ToString());

proper way assign numer to elements in a List Collection

I am looping through a list of elements, and would like to assign a number to where each element resides in the Collection for deletion puposes. My code below, just gives me the count, is there another option to achieve this. Ex.
0 cat
1 dog
2 fish
ect..
foreach (string x in localList)
{
{
Console.WriteLine( localList.Count + " " + x);
}
}
be old school and go back to a standard for loop:
for(int i = 0; i < localList.Count; ++i)
{
string x = localList[i];
// i is the index of x
Console.WriteLine(i + " " + x);
}
If you really want to get fancy, you can use LINQ
foreach (var item in localList.Select((s, i) => new { Animal = s, Index = i }))
{
Console.WriteLine(item.Index + " " + item.Animal);
}
you have to use a for loop or use a separate index:
for(int i = 0; i < localList.Count;i++)
{
Console.WriteLine( i + " " + localList[i]);
}
Depending on the collection type you are using you can use something like
foreach (string x in locallist)
{
Console.WriteLine(locallist.IndexOf(x) + " " + x);
}
regds, perry

Categories

Resources