C# creating an object using an array as the basis? - c#

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.

Related

C# Smarter way to output an Array

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';
}

Sorting number in richtextbox in c#

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.

c# how to put several groups of words from textfile into arrays

i have a textfile containing these kind of words
PEOPLE
John
0218753458
ENTERPRISE
stock
30%
HOME
Indiana
West Virginia
PEOPLE
Vahn
031245678
ENTERPRISE
Inc
50%
HOME
melbourne
Australia
i want to split these files into some strings that will divide the into each groups of PEOPLE, ENTERPRISE, and HOME. for example the output will be
part[0]
PEOPLE
John
0218753458
part[1]
ENTERPISE
stock
30%
part[2]
HOME
Indiana
West Virginia
and so on
i have a plan of using
EDIT #1 (thanks #Slade)
string[] part = s.Split(new string[] { "PEOPLE","ENTERPRISE","HOME" }, StringSplitOptions.None);
i can't change the structure.
is there any way to keep the HEADER? or better way to do this?
Don't use the || operator, that's for conditional/logical OR expressions. Instead, when filling elements of an array like you are doing, use a comma, like so:
string[] part = s.Split(new string[] { "PEOPLE", "ENTERPRISE", "HOME" }, StringSplitOptions.None);
However, unless you are always going to have these headings, it is not a good way of trying to split your text file. Instead, you need to define some structure to your file. For example, if you are always going to have headers in FULL CAPS, then you may want to start by splitting your text file into lines, then looping through each element and group the elements each time you hit a line containing only characters in FULL CAPS.
Personally, if possible, I would change the text file structure so you can flag headers with some symbol before or after: e.g. :THIS IS A HEADER. That way, you can split into lines then just look for the : symbol at the start of a line.
EDIT
For a sample approach on how to go about parsing this with the FULL CAPS headers, see my code example on PasteBin.
Note: The line ...
string[] lines = File.ReadAllLines(#"Sample.txt");
... could be replaced with ...
string textFromFile = File.ReadAllText(#"Sample.txt");
string[] lines = textFromFile.Split(new string[1] { System.Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
Using regex and because you want to keep the split strings in the results:
string[] tmp = Regex.Split(originalString, #"(PEOPLE|ENTERPRISE|HOME)");
List result = new List();
for(var i = 1; i < tmp.Count() - 1; i += 2) {
result.Add(tmp[i] + tmp[i+1]);
}
This gives you the result you want.
The reason why I'm concatenating the tmp array is because as of .NET 2.0, the Regex.Split will return the split strings as part of the array. I also start the indexing at 1 because we want our concatenation to happen late
s.Split(new string[] {"PEOPLE", "ENTERPRISE", ... }, StringSplitOptions.RemoveEmptyEntries);
And if you want save headers itself than possiblle it will be preferable to split your string multiple times by each arguments and add header by hands. For example you split your string by People and add people header to each chunk. Then split each chunk by HOME and add HOME header by hands and so on.
I'm going to give an answer that doesn't exactly match up with what you've asked for, so if you're dead set on having the output you've defined in your question then please disregard. Otherwise, I hope this is useful;
var peopleList = new List<string>();
var enterpriseList = new List<string>();
var homeList = new List<string>();
List<string> workingList = null;
using (var reader = new StreamReader("input.txt"))
{
string line = reader.ReadLine();
while (line != null)
{
switch (line)
{
case "PEOPLE": { workingList = peopleList; } break;
case "ENTERPRISE": { workingList = enterpriseList; } break;
case "HOME": { workingList = homeList; } break;
default: { workingList.Add(line); } break;
}
line = reader.ReadLine();
}
}
Based on your sample input, this will populate three lists as follows;
peopleList = { "John", "0218753458", "Vahn", "031245678" }
enterpriseList = { "stock", "30%", "Inc", "50%" }
homeList = { "Indiana", "West Virginia", "melbourne", "Australia" }

Extracting values from a string in C#

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.

C# how to split a string backwards?

What i'm trying to do is split a string backwards. Meaning right to left.
string startingString = "<span class=\"address\">Hoopeston,, IL 60942</span><br>"
What I would do normally is this.
string[] splitStarting = startingString.Split('>');
so my splitStarting[1] would = "Hoopeston,, IL 60942</span"
then I would do
string[] splitAgain = splitStarting[1].Split('<');
so splitAgain[0] would = "Hoopeston,, IL 60942"
Now this is what I want to do, I want to split by ' ' (a space) reversed for the last 2 instances of ' '.
For example my array would come back like so:
[0]="60942"
[1]="IL"
[2] = "Hoopeston,,"
To make this even harder I only ever want the first two reverse splits, so normally I would do something like this
string[] splitCity,Zip = splitAgain[0].Split(new char[] { ' ' }, 3);
but how would you do that backwards? The reason for that is, is because it could be a two name city so an extra ' ' would break the city name.
Regular expression with named groups to make things so much simpler. No need to reverse strings. Just pluck out what you want.
var pattern = #">(?<city>.*) (?<state>.*) (?<zip>.*?)<";
var expression = new Regex(pattern);
Match m = expression .Match(startingString);
if(m.success){
Console.WriteLine("Zip: " + m.Groups["zip"].Value);
Console.WriteLine("State: " + m.Groups["state"].Value);
Console.WriteLine("City: " + m.Groups["city"].Value);
}
Should give the following results:
Found 1 match:
1. >Las Vegas,, IL 60942< has 3 groups:
1. Las Vegas,, (city)
2. IL (state)
3. 60942 (zip)
String literals for use in programs:
C#
#">(?<city>.*) (?<state>.*) (?<zip>.*?)<"
One possible solution - not optimal but easy to code - is to reverse the string, then to split that string using the "normal" function, then to reverse each of the individual split parts.
Another possible solution is to use regular expressions instead.
I think you should do it like this:
var s = splitAgain[0];
var zipCodeStart = s.LastIndexOf(' ');
var zipCode = s.Substring(zipCodeStart + 1);
s = s.Substring(0, zipCodeStart);
var stateStart = s.LastIndexOf(' ');
var state = s.Substring(stateStart + 1);
var city = s.Substring(0, stateStart );
var result = new [] {zipCode, state, city};
Result will contain what you requested.
If Split could do everything there would be so many overloads that it would become confusing.
Don't use split, just custom code it with substrings and lastIndexOf.
string str = "Hoopeston,, IL 60942";
string[] parts = new string[3];
int place = str.LastIndexOf(' ');
parts[0] = str.Substring(place+1);
int place2 = str.LastIndexOf(' ',place-1);
parts[1] = str.Substring(place2 + 1, place - place2 -1);
parts[2] = str.Substring(0, place2);
You can use a regular expression to get the three parts of the string inside the tag, and use LINQ extensions to get the strings in the right order.
Example:
string startingString = "<span class=\"address\">East St Louis,, IL 60942</span><br>";
string[] city =
Regex.Match(startingString, #"^.+>(.+) (\S+) (\S+?)<.+$")
.Groups.Cast<Group>().Skip(1)
.Select(g => g.Value)
.Reverse().ToArray();
Console.WriteLine(city[0]);
Console.WriteLine(city[1]);
Console.WriteLine(city[2]);
Output:
60942
IL
East St Louis,,
How about
using System.Linq
...
splitAgain[0].Split(' ').Reverse().ToArray()
-edit-
ok missed the last part about multi word cites, you can still use linq though:
splitAgain[0].Split(' ').Reverse().Take(2).ToArray()
would get you the
[0]="60942"
[1]="IL"
The city would not be included here though, you could still do the whole thing in one statement but it would be a little messy:
var elements = splitAgain[0].Split(' ');
var result = elements
.Reverse()
.Take(2)
.Concat( new[ ] { String.Join( " " , elements.Take( elements.Length - 2 ).ToArray( ) ) } )
.ToArray();
So we're
Splitting the string,
Reversing it,
Taking the two first elements (the last two originally)
Then we make a new array with a single string element, and make that string from the original array of elements minus the last 2 elements (Zip and postal code)
As i said, a litle messy, but it will get you the array you want. if you dont need it to be an array of that format you could obviously simplfy the above code a little bit.
you could also do:
var result = new[ ]{
elements[elements.Length - 1], //last element
elements[elements.Length - 2], //second to last
String.Join( " " , elements.Take( elements.Length - 2 ).ToArray( ) ) //rebuild original string - 2 last elements
};
At first I thought you should use Array.Reverse() method, but I see now that it is the splitting on the ' ' (space) that is the issue.
Your first value could have a space in it (ie "New York"), so you dont want to split on spaces.
If you know the string is only ever going to have 3 values in it, then you could use String.LastIndexOf(" ") and then use String.SubString() to trim that off and then do the same again to find the middle value and then you will be left with the first value, with or without spaces.
Was facing similar issue with audio FileName conventions.
Followed this way: String to Array conversion, reverse and split, and reverse each part back to normal.
char[] addressInCharArray = fullAddress.ToCharArray();
Array.Reverse(addressInCharArray);
string[] parts = (new string(addressInCharArray)).Split(new char[] { ' ' }, 3);
string[] subAddress = new string[parts.Length];
int j = 0;
foreach (string part in parts)
{
addressInCharArray = part.ToCharArray();
Array.Reverse(addressInCharArray);
subAddress[j++] = new string(addressInCharArray);
}

Categories