Hi I am in a bit of an issue I keep getting this error:
Index was outside the bounds of the array.
var d = File.ReadAllLines(#"studentsFile.txt");
var t = d.Where(g => g.Contains("Student Name"));
string[] splited;
foreach (var item in t)
{
splited = item.Split(new string[] { "Student Name:" }, StringSplitOptions.None);
cbListStudents.Items.Add(splited[1]);
}
The above works perfectly but the code below does not:
var cour = File.ReadAllLines(#"CourseFile.txt");
var courFind = cour.Where(g => g.Contains("Course"));
string[] splited2;
foreach (var item in courFind)
{
splited2 = item.Split(new string[] { "Course:" }, StringSplitOptions.None);
cbListCourses.Items.Add(splited2[1]);//here is where the issues starts
}
At least you should check the array length:
var cour = File.ReadAllLines(#"CourseFile.txt");
var courFind = cour.Where(g => g.Contains("Course"));
string[] splited2;
foreach (var item in courFind)
{
splited2 = item.Split(new string[] { "Course:" }, StringSplitOptions.None);
if(splited2.Length >= 2)
cbListCourses.Items.Add(splited2[1]);//here is where the issues starts
}
foreach (var item in courFind)
{
splited2 = item.Split(new string[] { "Course:" }, StringSplitOptions.None);
cbListCourses.Items.Add(splited2[0]); // Array Index starts with 0
}
You have to check array's Length (what if the file has, say, empty lines?)
var data = File
.ReadLines(#"CourseFile.txt")
.Select(line => new string[] { "Course:" }, StringSplitOptions.None)
.Where(items => item.Length >= 2) // Check array's Length
.Select(items => items[1]) // Now it's safe to address the 2nd item
.ToArray(); // ComboBox.Items.AddRange wants array
cbListCourses.Items.AddRange(data);
The file might not contain any colon character (:) in the line.
You should check as if
var courFind = cour.Where(g => g.Contains("Course:"));
instead of the previous.
Test cases followed:
File with Empty content
with content -> Course:
with content -> Course (Error same as you faced)
Code:
var cbListStudents = new List<String> ();
var cbListCourses = new List<String> ();
var d = File.ReadAllLines (#"res/TestFile.txt");
var t = d.Where (g => g.Contains ("Student Name"));
string[] splited;
foreach (var item in t) {
splited = item.Split (new string[] { "Student Name:" }, StringSplitOptions.None);
cbListStudents.Add (splited[1]);
}
var cour = File.ReadAllLines (#"res/TestFile2.txt");
var courFind = cour.Where (g => g.Contains ("Course"));
string[] splited2;
foreach (var item in courFind) {
splited2 = item.Split (new string[] { "Course:" }, StringSplitOptions.None);
cbListCourses.Add (splited2[1]); //here is where the issues starts
}
Related
i have a string array
string[] lines=File.ReadAllLines(path);
The lines contains the below data
"A|3232|test"
"C|5544|test2"
"C|8884|test3"
"A|7777|test0"
"A|4343|test4"
I want to seperate the above array based on first letter "A" and "C". How to seperate the above lines and store in the bleow list strings.
List<string> aletterlines=
List<string> CletterLines=
You can do this with Linq:
var lineGroups = lines.GroupBy(d => d[0]);
List<string> aLetters = lineGroups.SingleOrDefault(d => d.Key == 'A').ToList();
List<string> cLetters = lineGroups.SingleOrDefault(d => d.Key == 'C').ToList();
string[] lines = File.ReadAllLines(path);
List<string> aletterlines = new List<string>();
List<string> CletterLines = new List<string>();
foreach (var item in lines)
{
string[] currentLine = item.Split('|');
if (currentLine[0] == "A")
{
aletterlines.Add(item);
}
else
{
CletterLines.Add(item);
}
}
There are many ways to achieve that, you can use LINQ as others suggested or a simple foreach loop:
private void Example()
{
string[] lines = {"A|3232|test",
"C|5544|test2",
"C|8884|test3",
"A|7777|test0",
"A|4343|test4"};
List<string> aletterlines = new List<string>();
List<string> CletterLines = new List<string>();
foreach (string item in lines)
{
if (item.StartsWith("A"))
{
aletterlines.Add(item);
}
else if (item.StartsWith("C"))
{
CletterLines.Add(item);
}
}
}
string format
addr,hname,beam,txrate,rxrate,dcap,ucap,txuse,rxuse,rxrssi0,rxrssi1,txrssi0,txrssi1,txper,rxper,txopqual
04:18:D6:bb:F4:C6,Name,0,270000,270000,295650,263250,31,17,35,36,37,35,124,229,0
desired output
addr = 04:18:D6:bb:F4:C6
hname = Name
beam = 0
and so on ...
...
i would like to pair in t key value but the key is a new line form the value and put them into a Dictionary for output use this code works, but I would like to know if there is a more efficient way to do this that will skip empty values
this is what i have so far
Dictionary<string, string> INFO = new Dictionary<string, string>();
var terminal = client.RunCommand("amstainfo");
var output = terminal.Result;
string[] line = output.Split(new string[] { "\n" }, StringSplitOptions.None);
string[] KEY = line[0].Split(new string[] { "," }, StringSplitOptions.None);
string[] VALUE = line[1].Split(new string[] { "," }, StringSplitOptions.None);
int i = 0;
foreach (var ist in KEY)
{
INFO.Add(KEY[i], VALUE[i]);
i++;
}
This seems fairly straight forward like this:
var lines = text.Split(
Environment.NewLine.ToCharArray(),
StringSplitOptions.RemoveEmptyEntries);
var INFO =
lines[0].Split(',')
.Zip(lines[1].Split(','), (key, value) => new { key, value })
.Where(x => !String.IsNullOrEmpty(x.value))
.ToDictionary(x => x.key, x => x.value);
This gives:
You can include an if statement in the foreach loop to check if the value is not empty or null before adding it to the dictionary.
foreach (var ist in KEY)
{
if(!string.IsNullOrEmpty(VALUE[i]))
{
INFO.Add(KEY[i], VALUE[i]);
}
i++;
}
i write a c# program that read data from 5 text files and count them according to some given key word
string[] word_1 = File.ReadAllText(#"C:\Users\Niyomal N\Desktop\Assignment\Assignment\D1_H1.txt").Split(' ');
string[] word_2 = File.ReadAllText(#"C:\Users\Niyomal N\Desktop\Assignment\Assignment\D2_H1.txt").Split(' ');
string[] word_3 = File.ReadAllText(#"C:\Users\Niyomal N\Desktop\Assignment\Assignment\D3_H2.txt").Split(' ');
string[] word_4 = File.ReadAllText(#"C:\Users\Niyomal N\Desktop\Assignment\Assignment\D4_H2.txt").Split(' ');
string[] word_5 = File.ReadAllText(#"C:\Users\Niyomal N\Desktop\Assignment\Assignment\D5_H2.txt").Split(' ');
string[] given_doc = File.ReadAllText(#"C:\Users\Niyomal N\Desktop\Assignment\Assignment\Given_doc.txt").Split(' ');
this is how i read from text files, after reading that i use for loop and if loop to count each word from hose file
for (int i = 0; i < word_1.Length; i++)
{
string s = word_1[i];
if ("Red".Equals(word_1[i]))
{
//Console.WriteLine(word[i]);
h1_r++;
}
if ("Green".Equals(word_1[i]))
{
h1_g++;
}
if ("Blue".Equals(word_1[i]))
{
h1_b++;
}
}
this is the loop i used to get the count from one file and its works fine, i did this process 5 times to read all files, my question is how can i read those 5 files using one for loop and store them in a array (count of each key word)
thanks in advance !!
LINQ query is your the simplest solution here:
var filenames = new[] { "D1_H1.txt", "D2_H1.txt", "D3_H2.txt" };
var words = new[] { "Red", "Green", "Blue" };
var counters =
filenames.Select(filename => Path.Combine(#"C:\Users\Niyomal N\Desktop\Assignment\Assignment", filename))
.SelectMany(filepath => File.ReadAllLines(filepath))
.SelectMany(line => line.Split(new[] { ' ' }))
.Where(word => words.Contains(word))
.GroupBy(word => word, (key, values) => new
{
Word = key,
Count = values.Count()
})
.ToDictionary(g => g.Word, g => g.Count);
and then you have dictionary of word counter within all files:
int redCount = counters["Red"];
If you want to store counters per each file, you can use slightly modified query:
var filenames = new[] { "D1_H1.txt", "D2_H1.txt", "D3_H2.txt" };
var words = new[] { "Red", "Green", "Blue" };
var counters =
filenames.Select(filename => Path.Combine(#"C:\Users\Niyomal N\Desktop\Assignment\Assignment", filename))
.Select(filepath => new
{
Filepath = filepath,
Count = File.ReadAllLines(filepath)
.SelectMany(line => line.Split(new[] { ' ' }))
.Where(word => words.Contains(word))
.GroupBy(word => word, (key, values) => new
{
Word = key,
Count = values.Count()
})
.ToDictionary(g => g.Word, g => g.Count)
})
.ToDictionary(g => g.Filepath, g => g.Count);
and then use it accordingly:
int redCount = counters[#"C:\Users\(...)\D1_H1.txt"]["Red"];
Copy pasting code is generally not good. It leads to code violating the Don't Repeat Yourself (DRY) rule. Restructure your code:
const string path = #"C:\Users\Niyomal N\Desktop\Assignment\Assignment";
string[] files = new string[] { "D1_H1.txt", "D2_H1.txt", "D3_H1.txt", ... };
foreach (string file in files) {
string fullPath = Path.Combine(path, file);
//TODO: count words of file `fullPath`
}
Storing the word counts in an array is not optimal as you will have to traverse the array for each word you are encountering in a file.
Use a dictionary instead which has a constant lookup time. That's much faster.
var wordCount = new Dictionary<string, int>();
You can then count the words like this:
int count;
if (wordCount.TryGetValue(word, out count)) {
wordCount[word] = count + 1;
} else {
wordCount[word] = 1;
}
UPDATE
You can test for keywords like this
var keywords = new HashSet<string> { "Red", "Green", "Blue" };
string word = "Green";
if (keywords.Contains(word)) {
...
}
HasSets are as fast as dictionaries.
Be careful with the word casing. HashSets are case sensitive by default. If "red" and "Red" and "RED" have to be found alltogehter, initialize the HashSet like this:
var keywords = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase)
{ "Red", "Green", "Blue" };
List<KeyValuePair<string, string>> completeList = new List<KeyValuePair<string, string>>();
completeList.AddRange("D1_H1.txt",File.ReadAllText(#"C:\Users\Niyomal N\Desktop\Assignment\Assignment\D1_H1.txt").Split(' '));
completeList.AddRange("D1_H2.txt", File.ReadAllText(#"C:\Users\Niyomal N\Desktop\Assignment\Assignment\D2_H1.txt").Split(' '));
completeList.AddRange("D1_H3.txt", File.ReadAllText(#"C:\Users\Niyomal N\Desktop\Assignment\Assignment\D3_H2.txt").Split(' '));
completeList.AddRange("D1_H4.txt", File.ReadAllText(#"C:\Users\Niyomal N\Desktop\Assignment\Assignment\D4_H2.txt").Split(' '));
completeList.AddRange("D1_H5.txt", File.ReadAllText(#"C:\Users\Niyomal N\Desktop\Assignment\Assignment\D5_H2.txt").Split(' '));
completeList.AddRange("D1_H6.txt", File.ReadAllText(#"C:\Users\Niyomal N\Desktop\Assignment\Assignment\Given_doc.txt").Split(' '));
var result = completeList.GroupBy(r => r.Key).Select(r => new {File = r.Key, Red = r.Count(s => s.Value == "red"), Green = r.Count(s => s.Value == "green"), Blue = r.Count(s => s.Value == "blue") });
foreach (var itm in result)
{
Console.WriteLine(itm.File);
Console.WriteLine(itm.Red);
Console.WriteLine(itm.Green);
Console.WriteLine(itm.Blue);
}
I am using the below code to read data from a text file row by row. I would like to assign each row into an array. I must be able to find the number or rows/arrays and the number of elements on each one of them.
I would also like to do some manipulations on some or all rows and return their values.
I get the number of rows, but is there a way to to loop something like:
*for ( i=1 to number of rows)
do
mean[i]<-row[i]
done
return mean*
var data = System.IO.File.ReadAllText("Data.txt");
var arrays = new List<float[]>();
var lines = data.Split(new[] {'\r', '\n'}, StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
var lineArray = new List<float>();
foreach (var s in line.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries))
{
lineArray.Add(Convert.ToSingle(s));
}
arrays.Add(lineArray.ToArray());
}
var numberOfRows = lines.Count();
var numberOfValues = arrays.Sum(s => s.Length);
var arrays = new List<float[]>();
//....your filling the arrays
var averages = arrays.Select(floats => floats.Average()).ToArray(); //float[]
var counts = arrays.Select(floats => floats.Count()).ToArray(); //int[]
Not sure I understood the question. Do you mean something like
foreach (string line in File.ReadAllLines("fileName.txt")
{
...
}
Is it ok for you to use Linq? You might need to add using System.Linq; at the top.
float floatTester = 0;
List<float[]> result = File.ReadLines(#"Data.txt")
.Where(l => !string.IsNullOrWhiteSpace(l))
.Select(l => new {Line = l, Fields = l.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) })
.Select(x => x.Fields
.Where(f => Single.TryParse(f, out floatTester))
.Select(f => floatTester).ToArray())
.ToList();
// now get your totals
int numberOfLinesWithData = result.Count;
int numberOfAllFloats = result.Sum(fa => fa.Length);
Explanation:
File.ReadLines reads the lines of a file (not all at once but straming)
Where returns only elements for which the given predicate is true(f.e. the line must contain more than empty text)
new { creates an anonymous type with the given properties(f.e. the fields separated by comma)
Then i try to parse each field to float
All that can be parsed will be added to an float[] with ToArray()
All together will be added to a List<float[]> with ToList()
Found an efficient way to do this. Thanks for your input everybody!
private void ReadFile()
{
var lines = File.ReadLines("Data.csv");
var numbers = new List<List<double>>();
var separators = new[] { ',', ' ' };
/*System.Threading.Tasks.*/
Parallel.ForEach(lines, line =>
{
var list = new List<double>();
foreach (var s in line.Split(separators, StringSplitOptions.RemoveEmptyEntries))
{
double i;
if (double.TryParse(s, out i))
{
list.Add(i);
}
}
lock (numbers)
{
numbers.Add(list);
}
});
var rowTotal = new double[numbers.Count];
var rowMean = new double[numbers.Count];
var totalInRow = new int[numbers.Count()];
for (var row = 0; row < numbers.Count; row++)
{
var values = numbers[row].ToArray();
rowTotal[row] = values.Sum();
rowMean[row] = rowTotal[row] / values.Length;
totalInRow[row] += values.Length;
}
How do you query a List<string[]> to get the index of the arrays having matches on their sub-arrays and get a return of type System.Collections.Generic.IEnumerable<string[]> ?
EDIT:
I have this:
string[] report = File.ReadAllLines(#".\REPORT.TXT").AsQueryable().Where(s
=> s.StartsWith(".|")).ToArray();
List<string[]> mylist = new List<string[]>();
foreach (string line in report)
{
string[] rows = line.Split('|');
mylist.Add(rows);
}
and I what to get the the mylist indexes where rows[5] == "foo"
For the original question:
list.Where(array => array.Any(item => item == match))
For the updated one:
result = Enumerable.Range(0, list.Count - 1).Where(i => list[i][5] == "foo");
You do actually need to check if the array has at least 6 items as well:
i => list[i].Length > 5 && list[i][5] == "foo"
You mean something like this?
var haystacks = new List<string[]>();
haystacks.Add(new string[] { "abc", "def", "ghi" });
haystacks.Add(new string[] { "abc", "ghi" });
haystacks.Add(new string[] { "def" });
string needle = "def";
var haystacksWithNeedle = haystacks
.Where(haystack => Array.IndexOf(haystack, needle) != -1);