I have a text file that looks like this
Words Words
Words Words
Words Words
1 34.4e+1
2 34.3e+1
3 34.2e+1
4 34.1e+1.... // and so on
I need to get the string number and concert it to decimal/double and then send it to an array where I can the use the array outside of the for loop to get the average via Enumerable.Chunk
decimal[] raw = new decimal[] { };
decimal[] rawAvgList = new decimal[] { };
decimal RawAvg = 0m;
try
{
string bPath = aPath + "\\" + fileName.Name + "\\textfilename.txt";
string[] readText = File.ReadAllLines(bPath);
readText = readText.Skip(3).ToArray();
foreach (var line in readText)
{
raw = new decimal[] { Decimal.Parse(line.Substring(9).ToString(), style1) };
for (int i = 0; i < raw.Length; i++)
{
Console.WriteLine("{0} \t {1}", raw[i], i++);
}
}
rawAvgList = raw.Chunk(20).Select(chunk => chunk.Average()).ToArray();
RawAvg = rawAvgList.Average();
}
So for when I call the array outside of the loop it only grabs the last number in the text file. Am I calling the information wrong? I swear I have tried all the different way to call the numbers from the text file and I just keep running into errors. The error range from it not liking me using skip and substring at the same time or and enumerable error where it returned the error and not the number. Anything to help, Thanks!
You are assigning the variable raw to a new value on each loop iteration, wiping out any value that was stored previously. The end result is that after the loop terminates, it will only contain the value from the last line in the file as you are seeing.
You can declare raw as a List<decimal> instead, then within the loop, you would do
raw.Add(Decimal.Parse(line.Substring(9).ToString(), style1));
This way, once the loop finishes, you'll have all the numbers and not just the last one.
Related
This question already has answers here:
Why does adding a new value to list<> overwrite previous values in the list<>
(2 answers)
Closed 11 months ago.
I'm using a for loop to read the lines of a file one by one. I then use the data in each line of the file to change the properties of the objects in an array.
I've run through the code in Debug mode, and it all seems to run fine. It reads the line of the file which corresponds to the i value of the for loop correctly, it defines an array of this data based on the commas, and it creates a temporary object which stores these values in the correct format. I know all of this because, as I've said, I have checked the values in Debug mode.
However, on the last line inside of the loop it seems to change every element in the array to the values stored in scrOldScore, whereas I want it to keep the values that it read in from
previous lines and just update the element of the array corresponding to the i of the for loop.
With each iteration of the for loop, the array holds identical data in each element that isn't null, and with each iteration that data changes to the most recently defined scrOldScore.
string str;
Data d = new Data();
for (int i = 0; i < arr.Length; i++)
{
str = File.ReadLines(FileName).Skip(i).Take(1).First(); ;
string[] string = new string[4];
string = str.Split(',');
d.Property01 = string[0];
d.Property02 = Convert.ToInt32(string[1]);
d.Property03 = string[2];
d.Property04 = string[3];
arr[i] = d;
}
Thanks for any help :)
The code doesn't work because it's putting the same ScoreData object instance in every array item. You need to create a new ScoreData object instance inside the loop.
But also the original code re-opens and reads through the file a little further on every iteration of the loop. This is grossly inefficient. You can make things run in a fraction of the time by keeping the same file handle, which you can do by using the file, rather than the array, as the main item for the loop:
int i = 0;
var lines = File.ReadLines(strFileName);
foreach(var line in lines)
{
var data = line.Split(',');
ScrScores[i] = new ScoreData() {
Name = data[0],
Score = int.Parse(data[1]),
Accuracy = data[2],
ReactionTime = data[3]
};
i++;
}
Of course, there's a chance here the file might be larger than the array. If that's possible, you should probably be using a List<ScoreData> rather than an array anyway:
var ScrScores = new List<ScrScores>();
var lines = File.ReadLines(FileName);
foreach(var line in lines)
{
var data = line.Split(',');
ScrScores.Add(new ScoreData() {
Name = data[0],
Score = int.Parse(data[1]),
Accuracy = data[2],
ReactionTime = data[3]
});
}
Failing both of these, I would open a StreamReader object, rather than using File.ReadLines(), and call it's ReadLine() method in each for loop iteration.
using (var rdr = new StreamReader(FileName))
{
for (int i = 0; i < ScrScores.Length; i++)
{
var data = rdr.ReadLine().Split(',');
ScrScores[i] = new ScoreData() {
Name = data[0],
Score = int.Parse(data[1]),
Accuracy = data[2],
ReactionTime = data[3]
};
}
}
One last thing we can do, since it looks like we're replacing all the elements in an array of known size, is replace the entire array. To do this we can read exactly that many items from the file and project them into ScoreData objects as we go:
ScrScores = File.ReadLines(FileName).
Select(line => line.Split(',')).
Select(data => new ScoreData() {
Name = data[0],
Score = int.Parse(data[1]),
Accuracy = data[2],
ReactionTime = data[3]
}).
Take(ScrScores.Length).
ToArray();
Technically, this is one line of code (only one semi-colon and could be extended to fit on the same line).
I'll add that hungarian notation variable prefixes like str and arr are a hold-over from the VB6 era. Today, tooling has improved and even Microsoft's own coding guidelines — where the practice originated — now specifically say (in bold type, no less) "Do not use Hungarian notation". All the code examples I provided reflect this recommendation.
My testerfile contains:
processes
deleting
agreed
And this the code in C#
PorterStemmer testing = new PorterStemmer();
string temp,stemmed;
string[] lines = System.IO.File.ReadAllLines(#"C:\\Users\\PJM\\Documents\\project\\testerfile.txt");
System.Console.WriteLine("Contents of testerfile.txt = ");
for (int i = 0; i <2; i++)
{
temp = lines[i];
stemmed = testing.StemWord(temp);
System.IO.File.WriteAllText(#"C:\\Users\\PJM\\Documents\\project\\testerfile3.txt", stemmed);
Console.WriteLine("\t" + stemmed);
}
After running the code, the testerfile3 contains only "agre" .
So my problem here is that I want each word in the string array to be processed seperately i.e. I am having problem accessing string array. Is there any way to access every index in the string array?
From the documentation of WriteAllText:
If the target file already exists, it is overwritten.
so each iteration in your for loop overwrites the file, and you're only left with the text from the last iteration.
you can use System.IO.File.AppendAllText instead
also, you can use the array's Length property to loop through all words for (int i = 0; i < lines.Length; i++)
Alternatively, instead of the for-loop you can use LINQ's Select to project the non-stemmed line to the stemmed one and use AppendAllLines to write the results:
System.IO.File.AppendAllLines(#"C:\\Users\\PJM\\Documents\\project\\testerfile3.txt", lines.Select(l => testing.StemWord(l)));
I have a textfile called 'tx1.text'. In this textfile, I have written on each line a number,
64
73
86
etc
I have 3 variables in the program, 'one' 'two' 'three', how can I assign the variables the values in the textfile line by line?
try this code
// Opne file and read all lines from file in string array
string[] values = File.ReadAllLines("tx1.txt");
// now get a number from string array and convert it to number
one = int.Parse(values[0]);
two = int.Parse(values[1]);
three = int.Parse(values[2]);
for further information about ReadAllLines method File.ReadAllLines
if you've many lines in text file and don't know the exact number then use can use for loop to iterate through but in this case you also have to use List or Array of integers to store int values
string[] lines = File.ReadAllLines("tx1.txt");
// creates an array of length equal to total numbers
int[] numbers = new int[lines.Length];
// use for loop to convert and store each number in array
for(int i = 0; i < lines.Length; i++)
{
numbers[i] = int.Parse(lines[i]);
}
I'm a C# newbie and I'm really confused about something I'm trying to do for a project in a C# class.
The assignment is some list manipulation in C#.
The program accepts a list of items in the text box, then iterates through those items, creating multiple copies of the list. It randomly resizes each copy of the list to between 3 and all items. It then outputs all the copies.
The problem I'm having is that when I step through this program with the debugger, I get the expected output. The same happens if I display a message box after each iteration (as I have in the code below).
However, if I just run the program straight through, I get a different output. Instead of variations in the lists, all the copies of the list are exactly the same.
If you see in the code I've commented "// FIRST DEBUG MESSAGEBOX" and "// SECOND DEBUG MESSAGEBOX". If the first debug messagebox code is left in there, the output is as expected...multiple versions of the list are output with random lengths between 3 and all items.
However, and this is where I'm confused...if you comment out the first debug messagebox code, you get a different result. All versions of the list output are the same length with no variation.
Any help would be appreciated! Here's the code I have so far...sorry if it's terrible - I'm new at C#:
public partial class MainForm : Form
{
/**
* Vars to hold raw text list items
* and list items split by line
*/
String rawListItems = "";
List<string> listItems = new List<string>();
List<List<string>> textListItems = new List<List<string>>();
public MainForm()
{
InitializeComponent();
}
private void cmdGo_Click(object sender, EventArgs e)
{
// store the contents of the list item text box
this.rawListItems = txtListItems.Text;
this.listItems.AddRange(Regex.Split(this.rawListItems, "\r\n"));
// setup min and max items - max items all items
int minItems = 3;
int maxItems = this.listItems.Count;
// We'll copy this list X times, X = same number of items in list
for (int i = 0; i < this.listItems.Count; i++)
{
// make a copy of the list items
List<string> listItemsCopy = new List<string>(this.listItems);
// get a random number between min items and max items
Random random = new Random();
int maxIndex = random.Next(minItems, maxItems + 1); // max is exclusive, hence the +1
// remove all elements after the maxIndex
for (int j = 0; j < listItemsCopy.Count; j++)
{
if (j > maxIndex)
{
listItemsCopy.RemoveAt(j);
}
}
// add the list copy to the master list
this.textListItems.Add(listItemsCopy);
// FIRST DEBUG MESSAGEBOX
String tst = "";
foreach (string item in listItemsCopy)
{
tst += item + " ## ";
}
MessageBox.Show(tst);
}
// SECOND DEBUG MESSAGEBOX
String output = "";
foreach (List<string> listitem in this.textListItems)
{
foreach (string item in listitem)
{
output += item + " ## ";
}
}
MessageBox.Show(output);
}
}
Move the creation of Random out of the loop:
Random random = new Random();
By default, the constructor uses a default time based seed. In a tight loop, you may be getting 'the same' random generator instead of a different one with each loop.
When using MessageBoxes or single stepping, you are allowing the timer to run and getting 'a new' random generator in each loop.
I don't understand your assignment exactly, but this loop seems to be incorrect:
for (int j = 0; j < listItemsCopy.Count; j++)
{
if (j > maxIndex)
{
listItemsCopy.RemoveAt(j);
}
}
when you remove an element in the middle of a list, elements after that get shifted, so not all the elements after maxIndex get removed, as you might expect.
In circumstances where stepping through the code in a debugger affects the behaviour of the program, a useful alternative debugging technique is to use the System.Diagnostics namespace in particular the Trace class.
The Trace functions work much like Console.WriteLine(), you can trace a string or a format string plus an array of objects to populate the format string, e.g.:
Trace.TraceInformation("some message that tells me something");
Trace.TraceInformation("some useful format string {1}, {0}",
new object[] {someObject, someOtherObject});
The program helps users to parse a text file by grouping certain part of the text files into "sections" array.
So the question is "Are there any methods to find out the line numbers/position within the array?" The program utilizes a foreach loop to read the "sections" array.
May someone please advise on the codes? Thanks!
namespace Testing
{
class Program
{
static void Main(string[] args)
{
TextReader tr = new StreamReader(#"C:\Test\new.txt");
String SplitBy = "----------------------------------------";
// Skip 5 lines of the original text file
for(var i = 0; i < 5; i++)
{
tr.ReadLine();
}
// Read the reststring
String fullLog = tr.ReadToEnd();
String[] sections = fullLog.Split(new string[] { SplitBy }, StringSplitOptions.None);
//String[] lines = sections.Skip(5).ToArray();
int t = 0;
// Tried using foreach (String r in sections.skip(4)) but skips sections instead of the Text lines found within each sections
foreach (String r in sections)
{
Console.WriteLine("The times are : " + t);
// Is there a way to know or get the "r" line number?
Console.WriteLine(r);
Console.WriteLine("============================================================");
t++;
}
}
}
}
A foreach loop doesn't have a loop counter of any kind. You can keep your own counter:
int number = 1;
foreach (var element in collection) {
// Do something with element and number,
number++;
}
or, perhaps easier, make use of LINQ's Enumerable.Select that gives you the current index:
var numberedElements = collection.Select((element, index) => new { element, index });
with numberedElements being a collection of anonymous type instances with properties element and index. In the case a file you can do this:
var numberedLines = File.ReadLines(filename)
.Select((Line,Number) => new { Line, Number });
with the advantage that the whole thing is processed lazily, so it will only read the parts of the file into memory that you actually use.
As far as I know, there is not a way to know which line number you are at within the file. You'd either have to keep track of the lines yourself, or read the file again until you get to that line and count along the way.
Edit:
So you're trying to get the line number of a string inside the array after the master string's been split by the SplitBy?
If there's a specific delimiter in that sub string, you could split it again - although, this might not give you what you're looking for, except...
You're essentially back at square one.
What you could do is try splitting the section string by newline characters. This should spit it out into an array that corresponds with line numbers inside the string.
Yes, you can use a for loop instead of foreach. Also, if you know the file isn't going to be too large, you can read all of the lines into an array with:
string[] lines = File.ReadAllLines(#"C:\Test\new.txt");
Well, don't use a foreach, use a for loop
for( int i = 0; i < sections.Length; ++ )
{
string section = sections[i];
int lineNum = i + 1;
}
You can of course maintain a counter when using a foreach loop as well, but there is no reason to since you have the standard for loop at your disposal which is made for this sort of thing.
Of course, this won't necessarily give you the line number of the string in the text file unless you split on Environment.NewLine. You are splitting on a large number of '-' characters and I have no idea how your file is structured. You'll likely end up underestimating the line number because all of the '---' bits will be discarded.
Not as your code is written. You must track the line number for yourself. Problematic areas of your code:
You skip 5 lines at the beginning of your code, you must track this.
Using the Split method, you are potentially "removing" lines from the original collection of lines. You must find away to know how many splits you have made, because they are an original part of the line count.
Rather than taking the approach you have, I suggest doing the parsing and searching within a classic indexed for-loop that visits each line of the file. This probably means giving up conveniences like Split, and rather looking for markers in the file manually with e.g. IndexOf.
I've got a much simpler solution to the questions after reading through all the answers yesterday.
As the string had a newline after each line, it is possible to split the strings and convert it into a new array which then is possible to find out the line number according to the array position.
The Codes:
foreach (String r in sections)
{
Console.WriteLine("The times are : " + t);
IList<String> names = r.Split('\n').ToList<String>();
}