I have a richtextbox with a lot of number And any number is in a special line and I want Sort The Numbers...
example:
<
99
1
12
1023
>
want to sort
<
1
12
99
1023
>
You can set the .Text property of a RichTextBox to the output from a String.Join if you just want every element to appear on its own line:
int[] numbers = new[] { 99, 1, 12, 1023 };
Array.Sort(numbers);
richTextBox1.Text = String.Join(Environment.NewLine, numbers);
It's difficult to tell what the problem is from your question. If you want to output sorted numbers together on a line with spaces between them, you can join on a space instead:
richTextBox1.Text = String.Format("< {0} >", String.Join(" ", numbers));
If you're trying to read in numbers in that sort of format, reorder them, and output in the same format, you'll have to parse the string for the individual numbers:
string inputRaw = "< 99 1 12 1023 >";
inputRaw = inputRaw.Trim(new[] { '<', '>' });
List<int> inputNumbers = new List<int>();
string[] temporary = inputRaw.Split(' ');
foreach (string s in temporary)
{
int n;
if (Int32.TryParse(s, out n))
inputNumbers.Add(n);
}
inputNumbers.Sort();
richTextBox1.Text = String.Format("< {0} >", String.Join(" ", inputNumbers));
Put the numbers into an array and then call the Array.Sort method.
If the textbox is just an output where you place those numbers, it'd be more smart to sort the values before placing them in the textbox using Array.sort.
If the textbox is actually an input where the user provides the values, you'll first want to take each line content and convert into a number, storing in an array as you go:
int[] linesAsNumbers = new int[richTextBox1.Lines.Length]; // We'll store the numbers in this array
int i = 0; // Keep an index of where to place the incoming numbers
foreach (string line in richTextBox1.Lines)
{
linesAsNumbers[i++] = Convert.ToInt32(line); // Convert each line into a number and store it into our newly created array
}
Now you'll have to sort the array using Array.Sort and join all the numbers back into a string:
Array.Sort(linesAsNumbers); // It automatically sorts from lowest to highest
richTextBox1.Text = String.Join<int>("\n", linesAsNumbers);
This of course chokes if any of the lines contains non-number characters, but works with your scenary.
Related
one of my first posts, so do not expect too much of me please.
I have an array
string phrase = Value.Text;
string[] words = phrase.Split('\t', '\r');
Which splits the output by tab or return.
I then re-arrange that array to create an output - this caused some confusion so updating...
The Input is from a Spreadsheet, as an example, the array will contain the number for each of the items, So:
TV is Four
Video is Five
Radio is Seven
string TV = words[3];
string Video = words[2];
string Radio = words[1];
Then create an output:
this.OutPut.Text = NumberValue.Text;
this.OutPut.Text += '\t';
this.OutPut.Text += TV;
this.OutPut.Text += '\t';
this.OutPut.Text += DatePicker.Text;
The NumberValue comes from a TextBox - imagine this is the price
The DatePicker comes from a Date picker - imagine this is the date that the information was created (not the day in which it is entered)
The purpose is to copy the data to a template spreadsheet. However, the data must match the destination template spreadsheet - hence the array and output re-arranging.
This has been fine, while dealing with a small array, and a defined length array works fine - for example, just TV, Video and Radio.
I am now seeking to have an array 'upto' 100, but could be less.
I realise that this code is not good as it is going to be 200 lines of code and it also throws "index out of range" exceptions whenever an array is created that does not reach the last words [100] created or output.
So I was wondering if anyone had a better way of doing this? I don't need you to write the code, but give me an idea, and I can go learn...but at the moment, I don't really know what I am looking for or how to search for it, as I doubt I have the language required to find it.
So any pointers gratefully received.
I hope the updates help explain the problem.
Without knowing more about your input/output, it's really hard to make useful suggestions.
Here's an idea that you might find useful, though. Use a List<string> to hold the order of the new items, then join them together when you need to combine then into one line.
Big picture idea:
string phrase = Value.Text;
string[] words = Value.Text.Split(new char[] { '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
List<string> values = new List<string>();
// add things to values, from words, in whatever order you need them to be
values.Add(words[3]);
values.Add(words[4]);
values.Add(words[1]);
string newLine = String.Join("\t", values);
OutPut.AppendText(newLine + Environment.NewLine);
If you already know the order of the indices, the "3", "4", "1" in my example, then you could use an ARRAY to hold those values and then iterate over them:
string phrase = Value.Text;
string[] words = Value.Text.Split(new char[] { '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
int[] newIndexOrder = { 3, 4, 1 };
List<string> values = new List<string>();
foreach(int i in newIndexOrder )
{
values.Add(words[i]);
}
string newLine = String.Join("\t", values);
OutPut.AppendText(newLine + Environment.NewLine);
string phrase = Value.Text;
string[] words = Value.Text.Split(new char[] { '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
From the comments:
if every 12 values/words I need a line break?
I've added in a StringBuilder to accumulate the output, adding in a break whenever we hit twelve items:
int[] newIndexOrder = { 3, 4, 1 };
List<string> values = new List<string>();
StringBuilder sb = new System.Text.StringBuilder();
foreach(int i in newIndexOrder)
{
values.Add(words[i]);
if (values.Count == 12)
{
sb.AppendLine(String.Join("\t", values));
values.Clear();
}
}
if (values.Count > 0)
{
sb.AppendLine(String.Join("\t", values));
}
OutPut.AppendText(sb.ToString());
You can use a foreach loop and avoid writing 200 lines of code.
Example :
string phrase = Value.Text;
string[] words = phrase.Split('\t', '\r');
foreach (string word in words)
{
this.OutPut.text += word + '\t';
}
This is more a question of whether this is possible.
I have an input box, 6 items go into the input box, this is an example string that forms the array:
Monday, Tuesday, April, February, Tomorrow, 42
These words can change, but their order is important. They are separated by a tab.
I want the 1st, 3rd, and the 6th word from this array. I would like to place them into an object - and if at all possible, but other items from other sources into that object in a particular order - so that I can then refer back to that object so that I do not have to write out long sections of code each time I need to output these 3 items.
My current code is unwieldy and I am looking for a better solution.
For reference my current code:
string phrase = value.Text;
string[] words = phrase.Split('\t');
string Word1 = words[1];
string Word2 = words[3];
string Word3 = words[6];
this.Output.Text = Word1 + '\t';
this.Output.Text += TextBox1.Text + '\t';
this.Output.Text += Word2 + '\t';
this.Output.Text += TextBox2.Text + '\t';
this.Output.Text += Word3;
This code works, but I am starting to work with larger arrays, requiring larger outputs and I am finding that I need to refer back to the same output multiple times.
Imagine the above code running to Word12, from an array of 30 adding the information from 6 text boxes, and having to have that output created 15 times in different places in the program. Also, you can see that the length of the code stops making sense.
If I could create an object containing all of that information, I could create it once, and then refer back to it as often as I needed.
Any insight or direction on how to proceed gratefully received.
Based on my understanding you are looking for below solution. If I missed something then please let me know.
Firstly you can store value.Text into a list of string by splitting by '\t'.
Create an array to store indexes for which you want to pick words.
Based on stored indexes you can pick words and store in a final wordslist.
Create an array to store dynamic textboxes text.
Loop on these stored textboxes text array and insert at alternate position in final wordlist.
At last join wordlist separated by '\t' and show as output.
Below is the code:
string finalOutput = string.Empty;
List<string> wordsList = new List<string>();
string phrase = value.Text;// "Monday\tTuesday\tApril\tFebruary\tTomorrow\t42";
string[] words = phrase.Split('\t');
List<int> wordsIndexes = new List<int> { 1, 3, 6 }; //this is based on ur requirment
List<string> textBoxesText = new List<string>() { TextBox1.Text, TextBox2.Text };
wordsIndexes.ForEach(i => wordsList.Add(words[i-1]));
int insertAtIndex = 1;
for (int i = 0; i < textBoxesText.Count; i++)
{
if (wordsList.Count >= insertAtIndex)
{
wordsList.Insert(insertAtIndex, textBoxesText[i]);
insertAtIndex += 2;
}
}
finalOutput = string.Join('\t', wordsList);
Not sure if I understand correctly, but I think that you could use a list and add the words there, using a list of indexes like so:
string phrase = value.Text;
string[] words = phrase.Split('\t');
List<int> indexes = new List<int> { 1, 3, 6 }; //you can add more indexes here...
List<string> wordsList = new List<string>();
indexes.Foreach(i => wordsList.add(words[i]));
With this implementation, you have all the words you need in the list and you can easily add more just adding or removing any index you want. And you can refer the list whenever you need to.
This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 6 years ago.
I ran into an exception "System.IndexOutOfRangeException" on a project and isolated into this example code block here.
using System;
public class Program
{
public static void Main()
{
string testStr = "AB5, BC4, CD8, DC8, DE6, AD5, CE2, EB3, AE7";
//split testStr into substrings representing each edge
string [] edges = testStr.Split(", ".ToCharArray());
foreach(string edge in edges)
{
Console.Write(edge + "\n");
char [] cEdge = edge.ToCharArray();
char cost = cEdge[cEdge.Length - 1]; // what out of bounds?
Console.Write(cost);
}
}
}
This issue comes from the line "char cost = cEdge[cEdge.Length - 1];". Which makes no sense to me since cEdge by this point should be an array of length 3. So indexing at cEdge.Length - 1 should be index of 2 and be within bounds of the array. I'm quite confused, maybe I've over looked something. Thanks for your time and help.
By default the Split method includes empty strings in the array. So you're cEdge array is has a size of 17 with around 8 of the elements being empty strings. So when you try iterating through the array, the length of the empty string is 0 and you try to subtract 1 which places you out of bounds on the array.
You've got a couple of options here. You can place an if statement to ensure the length of cEdge is 3 characters or update the Split method to use one of the overloads that will automatically remove these empty elements.
Here's how you would use the overload:
string[] edges = testStr.Split(", ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
Edit
Just realized I didn't really explain why you get the extra empty groups. The empty elements appear because you supplied the split function with an array of delimiters. The function then uses the array to match on ANY one of the delimiters and breaks it into unique elements. There's a perfect example in you're situation where this makes a difference. If your source string testStr was to contain a space in one of the fields it will actually break that field in half because you supplied a space into the delimiter list.
As the MSDN article puts it:
Each element of separator defines a separate delimiter character. If two delimiters are adjacent, or a delimiter is found at the beginning or end of this instance, the corresponding array element contains Empty.
So for instance:
string testStr = "AB5, BC4, CD8 Test, DC8";
string [] edges = testStr.Split(", ".ToCharArray());
In this case most people assume that we would end up with an array that looks something like this:
+----------------------------+
| AB5 | BC4 | CD8 Test | DC8 |
+----------------------------+
However the actual output of this method would be more like this:
+------------------------------+
| AB5 | BC4 | CD8 | Test | DC8 |
+------------------------------+
To get the desired output every time, a more robust solution would look something like this:
String[] edges = Regex.Split(testStr, Regex.Escape(", "), RegexOptions.None);
If the split happens to be within a tight loop you may want to consider compiling the regex before entering the loop, but that's a different problem.
The problem is when the array is empty Length property will equal to 0 and cEdge[0 - 1] will eventually give you IndexOutOfRangeException. Consider checking Length before indexing array:
using System;
public class Program
{
public static void Main()
{
string testStr = "AB5, BC4, CD8, DC8, DE6, AD5, CE2, EB3, AE7";
//split testStr into substrings representing each edge
string [] edges = testStr.Split(", ".ToCharArray());
foreach(string edge in edges)
{
Console.Write(edge + "\n");
char [] cEdge = edge.ToCharArray();
if (cEdge.Length > 0)
{
char cost = cEdge[cEdge.Length - 1]; // what out of bounds?
Console.Write(cost);
}
}
}
}
Because the 2nd,4th,6th,etc... array value of edges in empty.
static void Main(string[] args)
{
string testStr = "AB5, BC4, CD8, DC8, DE6, AD5, CE2, EB3, AE7";
//split testStr into substrings representing each edge
string[] edges = testStr.Split(", ".ToCharArray());
char[] cEdge;
foreach (string edge in edges)
{
Console.Write(edge + "\n");
cEdge = edge.ToCharArray();
char cost = new char();
if(cEdge.Length > 0)
{
cost = cEdge[0]; // what out of bounds?
}
Console.Write(cost);
}
Console.Read();
}
I trace Your code and i found edge value contains "" that causes cEdge.Length is 0
you must fixed you code like this:
public static void Main()
{
string testStr = "AB5, BC4, CD8, DC8, DE6, AD5, CE2, EB3, AE7";
//split testStr into substrings representing each edge
string[] temp = { ", " };
string[] edges = testStr.Split(temp, StringSplitOptions.RemoveEmptyEntries);
foreach (string edge in edges)
{
Console.Write(edge + "\n");
char[] cEdge = edge.ToCharArray();
char cost = cEdge[cEdge.Length - 1]; // what out of bounds?
Console.Write(cost);
}
}
You splitting a string by char array of ',' and ' '
and you get something like:
["AB5","","BC4","", ....]
look here http://msdn.microsoft.com/en-us/library/b873y76a(v=vs.110).aspx
In this line than edge == ""
char cost = cEdge[cEdge.Length - 1];
cEdge.Length == 0
and you get System.IndexOutOfRangeException
You should use following syntax
testStr.Split(", ".ToCharArray(),StringSplitOptions.RemoveEmptyEntries);
In fact, i'd like to match the things before and after the " ??"
my code is below:
//enter code here
Regex r = new Regex(#"(?'value'[0-9\-\./TSE]{1,}) \?\?(?'index'[A-Za-z:]{1,}");
string s=
#"39 ??Issue:
9 ??Pages:
1307-1325 ??DOI:
10.1109/TSE.2013.14 ??Published:";
As you can see, i'd like to match these things:
value="39" index = "Issue:"
value="9" index = "Pages:"
value="1307-1325" index = "DOI:"
value="10.1109/TSE.2013.14" index = "Published:"
I think just change one or two characters in the regex can solve this problem. anyone can help?
If you simply want the information before and after the ??, and it will always be in that format (value ?? index), then Regex is way overkill for this. Simply use String.Split:
string s= #"39 ??Issue:
9 ??Pages:
1307-1325 ??DOI:
10.1109/TSE.2013.14 ??Published:";
string[] splitValues = s.Split(new string[] { "??", "\r\n" }, StringSplitOptions.None);
for (int i = 0; i < splitValues.Length; i += 2)
{
Console.WriteLine("value={0} index={1}", splitValues[i].Trim(), splitValues[i + 1].Trim());
}
This will split on the ?? and the newline, resulting in the output you're looking for:
value="39" index = "Issue:"
value="9" index = "Pages:"
value="1307-1325" index = "DOI:"
value="10.1109/TSE.2013.14" index = "Published:"
The coded above splits the string on ?? and \r\n (end of line/newline), resulting in an array of elements, with the first element being the first value, the second element being the second value, the third element being the first value of the second line, the fourth element being the second value of the second line, etc.
The for loop is pretty straight forward - the i += 2 part simply increments the loop counter by 2 (instead of the usual 1 [i++]), so it prints the value and index of each line in the input.
I have the following string which i would like to retrieve some values from:
============================
Control 127232:
map #;-
============================
Control 127235:
map $;NULL
============================
Control 127236:
I want to take only the Control . Hence is there a way to retrieve from that string above into an array containing like [127232, 127235, 127236]?
One way of achieving this is with regular expressions, which does introduce some complexity but will give the answer you want with a little LINQ for good measure.
Start with a regular expression to capture, within a group, the data you want:
var regex = new Regex(#"Control\s+(\d+):");
This will look for the literal string "Control" followed by one or more whitespace characters, followed by one or more numbers (within a capture group) followed by a literal string ":".
Then capture matches from your input using the regular expression defined above:
var matches = regex.Matches(inputString);
Then, using a bit of LINQ you can turn this to an array
var arr = matches.OfType<Match>()
.Select(m => long.Parse(m.Groups[1].Value))
.ToArray();
now arr is an array of long's containing just the numbers.
Live example here: http://rextester.com/rundotnet?code=ZCMH97137
try this (assuming your string is named s and each line is made with \n):
List<string> ret = new List<string>();
foreach (string t in s.Split('\n').Where(p => p.StartsWith("Control")))
ret.Add(t.Replace("Control ", "").Replace(":", ""));
ret.Add(...) part is not elegant, but works...
EDITED:
If you want an array use string[] arr = ret.ToArray();
SYNOPSYS:
I see you're really a newbie, so I try to explain:
s.Split('\n') creates a string[] (every line in your string)
.Where(...) part extracts from the array only strings starting with Control
foreach part navigates through returned array taking one string at a time
t.Replace(..) cuts unwanted string out
ret.Add(...) finally adds searched items into returning list
Off the top of my head try this (it's quick and dirty), assuming the text you want to search is in the variable 'text':
List<string> numbers = System.Text.RegularExpressions.Regex.Split(text, "[^\\d+]").ToList();
numbers.RemoveAll(item => item == "");
The first line splits out all the numbers into separate items in a list, it also splits out lots of empty strings, the second line removes the empty strings leaving you with a list of the three numbers. if you want to convert that back to an array just add the following line to the end:
var numberArray = numbers.ToArray();
Yes, the way exists. I can't recall a simple way for It, but string is to be parsed for extracting this values. Algorithm of it is next:
Find a word "Control" in string and its end
Find a group of digits after the word
Extract number by int.parse or TryParse
If not the end of the string - goto to step one
realizing of this algorithm is almost primitive..)
This is simplest implementation (your string is str):
int i, number, index = 0;
while ((index = str.IndexOf(':', index)) != -1)
{
i = index - 1;
while (i >= 0 && char.IsDigit(str[i])) i--;
if (++i < index)
{
number = int.Parse(str.Substring(i, index - i));
Console.WriteLine("Number: " + number);
}
index ++;
}
Using LINQ for such a little operation is doubtful.