In order to train my coding foo, I have decide to register on the CodeEval platform. I stumble upon an exercise which I thought was pretty simple, but some reason, there is a bug that I cannot resolve since a long time ago.
Here's the situation (I've put only what seem to be more important from the text):
"the participants calculated votes that they received for each painting and inserted them in the table. But, they could not determine which movement has won and whose work received the highest score, so they asked you to help.
You need to determine and print the highest score of each category in the table."
More on the exercice on the following link :
https://www.codeeval.com/open_challenges/208/
This is a sample input that the platform uses to verify that my algorithm is OK:
333 967 860 -742 -279 -905 |
-922 380 -127 630 38 -548 |
258 -522 157 -580 357 -502 |
963 486 909 -416 -936 -239 |
517 571 107 -676 531 -782 |
542 265 -171 251 -93 -638
Here's my output from this sample :
967 630 357 963 571
At first, I couldn't understand what was wrong. But it seems that after the last
"|", my code freezes and "jumps" on the second line from the file I'm reading. My code looked pretty ok for what I was doing.
Here is the sample code :
//Sample code to read in test cases:
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System;
class Program
{
static void Main(string[] args)
{
using (StreamReader reader = File.OpenText(args[0]))
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
if (null == line)
continue;
List<int> highestScores = new List<int>();
var temporaryNumbers = new List<int>();
string[] splittedLine = line.Split(' ');
foreach (var s in splittedLine)
{
if (s == "|")
{
highestScores.Add(temporaryNumbers.Max());
temporaryNumbers.Clear();
continue;
}
int value;
if (int.TryParse(s, out value))
{
temporaryNumbers.Add(value);
continue;
}
continue;
}
if(highestScores.Count == 0)
continue;
var newLine = highestScores.Aggregate(string.Empty, (current, value)=> current + (value + " "));
Console.Out.WriteLine(newLine);
}
}
}
I guess my question would how to fix a situation like this ? It's not jump one line from the input that they use, it's every line. At the last |, the code jumps to the next line, if ever there is one.
In broad strokes, this is how I'd go about handling this:
First split your string into rows using Split("|") (let's call the resulting array rows). Now create a List<int> called columnMax. Now loop through rows and for each row we will Split(" ") (let's call this cells). Now we know (from the original assignment) that we can assume that rows are all the same length, so we will loop through cells using a for loop and check:
var value = int.Parse(cells[i]); // leaving out error checking for now
// but you could use TryParse to catch bad data
if (columnMax.Count <= i)
{
columnMax.Add(value);
}
else if (columnMax[i] < value)
{
columnMax[i] = value;
}
Now at the end of your loop, columnMax should contain all the maximums for each column (i.e. category).
Just for kicks, here's a Linq solution:
var maximums = input.Split(new [] {'|'}, StringSplitOptions.RemoveEmptyEntries)
.Aggregate((IEnumerable<int>)null,(m,r) =>
{
var cells = r.Split(new [] {' '}, StringSplitOptions.RemoveEmptyEntries).Select(c => int.Parse(c));
return m == null ? cells : cells.Zip(m, Math.Max);
});
I was going to post the whole solution, but as I see is a contest where you're participating.
So this is my help:
Try to split your problem in little problems and resolve one thing at a time. Actually your code is a little bit messi.
At first create a method to load all file entries and return a string collection with people scores for each line in the file . This would require a few more methods to convert string[] to int[], like this one.
static void StringToIntegers()
{
var input = "333 967 860 -742 -279 -905 | -922 380 -127 630 38 -548 | 258 -522 157 -580 357 -502 | 963 486 909 -416 -936 -239 | 517 571 107 -676 531 -782 | 542 265 -171 251 -93 -638";
var primaryArray = input.Split('|');
foreach (var block in primaryArray)
{
var trimmedBlock = block.Trim();
var secondaryArray = trimmedBlock.Split(' ');
var intArray = StringArrToIntArr(secondaryArray);
}
}
private static int[] StringArrToIntArr(string[] secondaryArray)
{
int[] intArray = new int[secondaryArray.Length];
for (int i = 0; i < secondaryArray.Length; i++)
{
if (!int.TryParse(secondaryArray[i], out intArray[i]))
throw new FormatException(string.Format("The string {0} is not a compatible int type",
secondaryArray[i]));
}
return intArray;
}
Then for each int collection call a method able to group each category score in different int arrays and there you can return the max number for each one.
Related
First of all, Hi to everyone. I'm a beginner with C# and trying to do this homework. My problem is, reading a specific part of a .pdb (protein data bank) file and split that specific lines into an array or list. Then I will use it for a Forms App
So .pdb file index is looks like this;
HEADER ANTIFREEZE 17-SEP-97 7MSI
TITLE TYPE III ANTIFREEZE PROTEIN ISOFORM HPLC 12
COMPND MOL_ID: 1;
COMPND 2 MOLECULE: TYPE III ANTIFREEZE PROTEIN ISOFORM HPLC 12;
SOURCE MOL_ID: 1;
SOURCE 2 ORGANISM_SCIENTIFIC: MACROZOARCES AMERICANUS;
ATOM 1 N MET A 0 18.112 24.345 32.146 1.00 51.10 N
ATOM 2 CA MET A 0 18.302 23.436 31.020 1.00 49.06 C
ATOM 3 C MET A 0 18.079 24.312 29.799 1.00 46.75 C
ATOM 4 O MET A 0 16.928 24.678 29.560 1.00 48.24 O
ATOM 5 CB MET A 0 17.257 22.311 31.008 1.00 48.14 C
ATOM 6 N ALA A 1 19.106 24.757 29.076 1.00 43.47 N
HETATM 491 O HOH A 101 23.505 19.335 23.451 1.00 35.56 O
HETATM 492 O HOH A 102 19.193 19.013 25.418 1.00 12.73 O
HETATM 493 O HOH A 103 7.781 12.538 12.927 1.00 80.11 O
....
and goes on like this
I only need to read the lines that starts with "ATOM" keyword. Then I want to split their informations to variables and to an array or list. After that I want to print the maximum value of X Coordinate to a label.
For example;
ATOM 1 N MET A 0 18.112 24.345 32.146 1.00 51.10 N
1 stands for atom number
N stands for atom name
MET stands for amino acid name
18.112 stands for X coordinate etc.
WHAT I DID
I used the codes from a similar question that was asked here before but i couldn't implement it to my project.
First I created a Class for variables
class Atom
{
public int atom_no;
public string atom_name;
public string amino_name;
public char chain;
public int amino_no;
public float x_coordinate;
public float y_coordinate;
public float z_coordinate;
public float ratio;
public float temperature;
}
For the main class; NOTE: I should mention that there's not single whitespace beetween variables. For example between "MET" and "A" there are extra 3 or 4 whitespaces. I've tried to remove them while reading file but I don't know if that worked..
private void button1_Click(object sender, EventArgs e)
{
string filePath = #"path_of_file";
string stringToSearch = #"ATOM";
List<Atom> Atoms = new List<Atom>();
using (StreamReader sr = new StreamReader(filePath))
{
string[] lines = File.ReadAllLines(filePath);
foreach (string line in lines)
{
if (line.Contains(stringToSearch)) // i have tried to read the parts that starts with ATOM
{
while (sr.Peek() >= 0) //this while part is from the question asked before
{
string[] strArray;
string line1 = sr.ReadLine(); // i've added theese 2 lines to remove the extra whitespaces
var lineParts = line1.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
strArray = line1.Split(' ');
Atom currentAtom = new Atom();
currentAtom.atom_no = int.Parse(strArray[0]);
currentAtom.atom_name = strArray[1];
currentAtom.amino_name = strArray[2];
currentAtom.chain = char.Parse(strArray[3]);
currentAtom.amino_no = int.Parse(strArray[4]);
currentAtom.x_coordinate = float.Parse(strArray[5]);
currentAtom.y_coordinate = float.Parse(strArray[6]);
currentAtom.z_coordinate = float.Parse(strArray[7]);
currentAtom.ratio = float.Parse(strArray[8]);
currentAtom.temperature = float.Parse(strArray[9]);
Atoms.Add(currentAtom);
}
}
}
}
listBox1.DataSource = Atoms;
listBox1.ValueMember = "atom_no";
listBox1.DisplayMember = "atom_name";
}
I didn't add the part that i want to print the max value of X Coordinate to a label yet. I'm testing at this point with listbox. So when I run the code and press the button gives me "Input string was not in a correct format" error at the currentAtom.atom_no = int.Parse(strArray[0]); line.
I know that my code looks like mess and sorry If I've stolen your time with this. I would be much appreciated if you guys can help me do this Forms app for my homework. If not, still thank you for reading it. Have a nice and healhty day..
One way to do this is to just use File.ReadAllLines to read the file, then filter out any lines that don't StartWith the stringToSearch text (using the System.Linq method Where), and finally select a new Atom from each line using the Split method (and remove empty entries) as you were doing, and finally returning them all with ToList:
List<Atom> Atoms = File.ReadAllLines(filePath) // Read all the lines
.Where(line => line.StartsWith(stringToSearch)) // Filter on our string
.Select(line =>
{
// Split the line on the space character into an array
var strArray = line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
// Return a new Atom for each line based on the array contents
return strArray.Length < 10 // Ensure we have at least ten elements in the array
? null // If we don't have 10, return 'null'
: new Atom // Otherwise return a new atom from the array
{
atom_no = int.Parse(strArray[0]),
atom_name = strArray[1],
amino_name = strArray[2],
chain = char.Parse(strArray[3]),
amino_no = int.Parse(strArray[4]),
x_coordinate = float.Parse(strArray[5]),
y_coordinate = float.Parse(strArray[6]),
z_coordinate = float.Parse(strArray[7]),
ratio = float.Parse(strArray[8]),
temperature = float.Parse(strArray[9])
};
})
.ToList(); // Return the items as a list
I have a text file which contains data. There are 3 columns, each column starts at a specific location and ends a specific location in the file. The first column which is (300, 301, 302, 304...) is always number based. the second column is a string, and the last column is currency.
The current .txt file is missing numbers which is (303, 305).
I was able to find the missing numbers and add it to an array then write it to the file.
My goal is to write all the columns data sequentially to the text file even the missing ones. As for column 2 and 3, I want 0 to be the placeholder for the missing data and aligned with its own column.
I'm close but need help
//read file
string[] lines = File.ReadAllLines(FilePath);
var Numbers = new List<int>();
int i = 0;
foreach (var line in lines)
{
//get value of first column
var FirstColumn = line.Substring(0, 3);
//add it to array
Numbers.Add(Convert.ToInt32(FirstColumn));
++i;
}
//find missing numbers add to array
var result = Enumerable.Range(Numbers.Min(), Numbers.Count);
//write to file
using (StreamWriter file = new StreamWriter(OutPutFile, true))
{
foreach (var item in result.ToArray())
{
file.WriteLine(item);
}
}
Console.ReadKey();
Current .txt file
300 Family Guy 1,123
301 Dexters Lab 456
302 Rugrats 1,789.52
304 Scooby-Doo 321
306 Recess 2,654
307 Popeye 1,987.02
GOAL: Desired Output .txt file
300 Family Guy 1,123
301 Dexters Lab 456
302 Rugrats 1,789.52
303 0 0
304 Scooby-Doo 321
305 0 0
306 Recess 2,654
307 Popeye 1,987.02
You are reading the first column, but not the rest. What I do is create a dictionary, using the first number as the index, and stuffing the other two fields into a System.ValueTuple (you need to include the ValueTyple Nuget package to get this to work).
First I set some stuff up:
const int column1Start = 0;
const int column1Length = 3;
const int column2Start = 8;
const int column2Length = 15;
const int column3Start = 24;
int indexMin = int.MaxValue; //calculated during the first
int indexMax = int.MinValue; //pass through the file
Then I create my dictionary. That (string, decimal) syntax describes a 2-tuple that contains a string and a decimal number (kind of like the ordered-pairs you were taught about in high school).
Dictionary<int, (string, decimal)> data = new Dictionary<int, (string, decimal)>();
Then I make a pass through the file's lines, reading through the data, and stuffing the results in my dictionary (and calculating the max and min values for that first column):
var lines = File.ReadAllLines(fileName);
foreach (var line in lines) {
//no error checking
var indexString = line.Substring(column1Start, column1Length);
var cartoon = line.Substring(column2Start, column2Length).TrimEnd();
var numberString = line.Substring(column3Start);
if (int.TryParse(indexString, out var index)) {
//I have to parse the first number - otherwise there's nothing to index on
if (!decimal.TryParse(numberString, out var number)){
number = 0.0M;
}
data.Add(index, (cartoon, number));
if (index < indexMin) {
indexMin = index;
}
if (index > indexMax) {
indexMax = index;
}
}
}
Finally, with all my data in hand, I iterate from the min value to the max value, fetching the other two columns out of my dictionary:
for (int i = indexMin; i <= indexMax; ++i) {
if (!data.TryGetValue(i, out var val)){
val = ("0", 0.0M);
}
Console.WriteLine($"{i,5} {val.Item1,-column2Length - 2} {val.Item2, 10:N}");
}
My formatting isn't quite the same as yours (I cleaned it up a bit). You can do what you want. My results look like:
300 Family Guy 1,123.00
301 Dexters Lab 456.00
302 Rugrats 1,789.52
303 0 0.00
304 Scooby-Doo 321.00
305 0 0.00
306 Recess 2,654.00
307 Popeye 1,987.02
I have sample.txt here:
ABCDEABCDEABCDEABCDE
1000 ABCDEABCDEABCDEABCDE
1001 BCDEABCDEABCDEABCDEA
1002 CDEABCDEABCDEABCDEAB
1003 DEABCDEABCDEABCDEABC
1004 EABCDEABCDEABCDEABCD
1005 AABBCCDDEEABCDEABCDE
1006 ABBCCDDEEAABCDEABCDE
1007 ACBEDADCEBBCDEAABABA
1008 AAAAAAAAAAAAAAAAAAAA
1009 BBBBBBBBBBBBBBBBBBBB
1010 EEEEEEEEEEEEEEEEEEEE
1011 CCCCCCCCCCCCCCCCCCCC
1012 DDDDDDDDDDDDDDDDDDDD
0000
first line is the standard answer, the following are the student ID (4 digits) and student answers(20 digits).
and the requirement is unless student ID =0000, else read the line to array.array[0]=student1 id,array[1]=student 1 answeer. or studentID[0]=student 1 ID, answer[0]=student 1 answer.
I am not familiar with while condition with increasing i.
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
int id;
string line;
string[] token;
var lineCount = File.ReadLines("C:\\testresult\\exam.txt").Count();
Console.WriteLine(lineCount);
string[] record = new string[lineCount];
try
{
StreamReader sr = new StreamReader("C:\\testresult\\exam.txt");
line = sr.ReadLine();
line = sr.ReadLine();
token = line.Split();
id = Convert.ToInt32(token[0]);
while (id != 0)
{
{
Console.WriteLine(token[1]);
line = sr.ReadLine();
token = line.Split();
id = Convert.ToInt32(token[0]);
for (int i = 0; i < lineCount; i = i + 2)
{
record[i]=Convert.ToString(id);
record[i + 1] = token[1];
Console.WriteLine(record[i], record[i + 1]);
}
}
}
sr.Close();
Console.ReadLine();
}
catch { }
}
}
}
can anyone advise how to read lines one by one and store the id and token[0] into each element in the array every time?
Let's run through a couple of basic learning points.
Don't do try...catch unless you're going to actually do something
with the exception.
StreamReader is IDisposable so should be in a using block
The posted code will iterate through the entire file twice. Not an issue for a small file; but I wanted to point that out.
Try to get into the habit of only declaring variables as close to the 'scope' that they are used in - it makes your code easier to read and maintain (e.g. when moving code around), and there is no performance hit for declaring local variables inside a loop.
String.Split will always give you one item (the zeroth) but you are using the 1st item token[1] without checking whether there is one, and there won't be when Id=0, which would give you an IndexOutOfRangeException.
You have a pair of matched braces for no apparent reason, which can and should be removed (keep your code simple).
You definitely seem confused in terms of having the for loop inside the while loop. Your while loop will be executed for each line in the file except the first one, so you just need to keep count of how many times you've been through the loop.
If you were going to make your code a bit more 'defensive' you could use int.TryParse rather than Convert.ToInt32; but I'm going to assume you're not worried about that.
So that would give you...
static void Main(string[] args)
{
var records = new List<string>();
foreach (string line in File.ReadLines("C:\\testresult\\exam.txt").Skip(1))
{
var tokens = line.Split();
int id = Convert.ToInt32(tokens[0]);
if (id == 0)
{
break;
}
else if (tokens.Length > 1)
{
// It looks like you want the Id and values to be put consecutively in the same array, which doesn't seem very useful.
// I would have thought a Dictionary<int,string> would be more useful... but here you go.
records.Add(id.ToString());
records.Add(tokens[1]);
}
}
// If you really want records to be an array you can use "records.ToArray()"
Console.ReadLine();
}
You can use Hash Table to record your data.
Ex:
//Record data to Hash Table
Hashtable hash = new Hashtable();
StreamReader sr = new StreamReader(#"C:\Users\Binh\Desktop\C#\test\exam.txt");
while(sr.EndOfStream == false)
{
string line = sr.ReadLine();
if(!line.StartsWith("0") && !Regex.IsMatch(line, #"^[A-Z]"))
{
string[] info = line.Split(' ');//Split string
string strudent_id = info[0];
string student_ans = info[1];
hash.Add(strudent_id, student_ans);
}
}
sr.Close();
//Watch the result
foreach (DictionaryEntry item in hash)
{
Console.WriteLine(item.Key + "," + item.Value);
//OUTPUT:
//1007,ACBEDADCEBBCDEAABABA
//1009,BBBBBBBBBBBBBBBBBBBB
//1010,EEEEEEEEEEEEEEEEEEEE
//1012,DDDDDDDDDDDDDDDDDDDD
//1001,BCDEABCDEABCDEABCDEA
//1002,CDEABCDEABCDEABCDEAB
//1004,EABCDEABCDEABCDEABCD
//1006,ABBCCDDEEAABCDEABCDE
//1008,AAAAAAAAAAAAAAAAAAAA
//1011,CCCCCCCCCCCCCCCCCCCC
//1000,ABCDEABCDEABCDEABCDE
//1003,DEABCDEABCDEABCDEABC
//1005,AABBCCDDEEABCDEABCDE
}
Ex : If you want to get answer of student with ID 1009
string answer = hash["1009"].ToString();
Console.WriteLine(answer);//Return BBBBBBBBBBBBBBBBBBBB
I have a CSV file (using ';' as the separator). I have used a StreamReader to read in each line of the file. The file contains almost 4000 rows and each row has 16 columns. I only need the last 5 numbers from each row, but I am unsure as to how to split each row and get only the last 5 numbers.
Example data:
2002;10;;0;0 EUR;122;448 823 EUR;8315;6 973 EUR;192233;586 EUR;6;13;55;66;81
2002;9;;0;0 EUR;62;750 138 EUR;4784;10 294 EUR;137390;697 EUR;13;51;55;62;74
2002;8;;0;0 EUR;56;801 650 EUR;6377;7 454 EUR;177197;522 EUR;12;13;19;28;85
So for the first row, the data I actually need is { 6; 13; 55; 66; 81 }
I am writing the part of the logic as per the example you provided. This would split one entire row and return you the last five numbers in an array.
string row = "2002; 10; ; 0; 0 EUR; 122; 448 823 EUR; 8315; 6 973 EUR; 192233; 586 EUR; 6; 13; 55; 66; 81";
string[] rowArray = row.Trim().Split(';');
string[] numbers = rowArray.Skip(Math.Max(0, rowArray.Length - 5)).ToArray();
numbers would contain all the last five numbers you want which you can access with the indexes- numbers[0], numbers[1], and so on.. upto numbers[4].
Note: You have to split the data as read from the StreamReader into rows. You you get the rows, loop through each row and use the above three lines of code to get the last five numbers.
You can do this easily with the String.Split method.
foreach(var line in file)
{
var result = test.Split(';');
var last = result.Length-1;
var first = result[last-4];
var second = result[last-3];
var third = result[last-2];
var fourth = result[last-1];
var fifth = result[last];
}
As a side note, a library that I have found very helpful when dealing with CSV files is LINQtoCSV. There is a NuGet package available so it can be easily added to a project. If you are going to have to do anything else with this data, you may want to check it out.
Edit:
Here is an example of doing this with LINQtoCSV. If you read the documentation they show how to set up a more strongly typed class that you could read into, for simplicity here I am just doing it in a raw fashion.
// Define the class for reading, both IDataRow and DataRowItem
// are part of the LINQtoCSV namespace
public class MyRow : List<DataRowItem>, IDataRow
{
}
// Create the context, the file description and then read the file.
var context = new CsvContext();
var inputFileDescription = new CsvFileDescription
{
SeparatorChar = ';',
FirstLineHasColumnNames = false, // Change this if yours does
};
// Note: You don't need to use your stream reader, just use the LINQtoCSV
// Read method to load the data into an IEnumerable. You can read the
// documentation for more information and options on loading/reading the
// data.
var products = context.Read<MyRow>(#"yourfile.csv", inputFileDescription);
// Iterate all the rows and grab the last 5 items from the row
foreach (var row in products)
{
var last = row.Count - 1;
var first = row[last - 4];
var second = row[last - 3];
var third = row[last - 2];
var fourth = row[last - 1];
var fifth = row[last];
}
You can try with Cinchoo ETL library, to parse the file and access the last 5 members as below
foreach (dynamic rec in new ChoCSVReader("quotes.csv").WithDelimiter(";"))
{
Console.WriteLine("{0}", rec[11]);
Console.WriteLine("{0}", rec[12]);
Console.WriteLine("{0}", rec[13]);
Console.WriteLine("{0}", rec[14]);
Console.WriteLine("{0}", rec[15]);
}
Example
If I had a text file with these lines:
The cat meowed.
The dog barked.
The cat ran up a tree.
I would want to end up with a matrix of rows and columns like this:
0 1 2 3 4 5 6 7 8 9
0| t-h-e- -c-a-t- -m-e-o-w-e-d-.- - - - - - - -
1| t-h-e- -d-o-g- -b-a-r-k-e-d-.- - - - - - - -
2| t-h-e- -c-a-t- -r-a-n- -u-p- -a- -t-r-e-e-.-
Then I would like to query this matrix to quickly determine information about the text file itself. For example, I would quickly be able to tell if everything in column "0" is a "t" (it is).
I realize that this might seem like a strange thing to do. I am trying to ultimately (among other things) determine if various text files are fixed-width delimited without any prior knowledge about the file. I also want to use this matrix to detect patterns.
The actual files that will go through this are quite large.
Thanks!
For example, I would quickly be able to tell if everything in column "0" is a "t" (it is).
int column = 0;
char charToCheck = 't';
bool b = File.ReadLines(filename)
.All(s => (s.Length > column ? s[column] : '\0') == charToCheck);
What you can do is read the first line of your text file and use it as a mask. Compare every next line to the mask and remove every character from the mask that is not the same as the character at the same position. After processing al lines you'll have a list of delimiters.
Btw, code is not very clean but it is a good starter I think.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace DynamicallyDetectFixedWithDelimiter
{
class Program
{
static void Main(string[] args)
{
var sr = new StreamReader(#"C:\Temp\test.txt");
// Get initial list of delimiters
char[] firstLine = sr.ReadLine().ToCharArray();
Dictionary<int, char> delimiters = new Dictionary<int, char>();
for (int i = 0; i < firstLine.Count(); i++)
{
delimiters.Add(i, firstLine[i]);
}
// Read subsequent lines, remove delimeters from
// the dictionary that are not present in subsequent lines
string line;
while ((line = sr.ReadLine()) != null && delimiters.Count() != 0)
{
var subsequentLine = line.ToCharArray();
var invalidDelimiters = new List<int>();
// Compare all chars in first and subsequent line
foreach (var delimiter in delimiters)
{
if (delimiter.Key >= subsequentLine.Count())
{
invalidDelimiters.Add(delimiter.Key);
continue;
}
// Remove delimiter when it differs from the
// character at the same position in a subsequent line
if (subsequentLine[delimiter.Key] != delimiter.Value)
{
invalidDelimiters.Add(delimiter.Key);
}
}
foreach (var invalidDelimiter in invalidDelimiters)
{
delimiters.Remove(invalidDelimiter);
}
}
foreach (var delimiter in delimiters)
{
Console.WriteLine(String.Format("Delimiter at {0} = {1}", delimiter.Key, delimiter.Value));
}
sr.Close();
}
}
}
"I am trying to ultimately (among other things) determine if various text files are fixed-width (...)"
If that's so, you could try this:
public bool isFixedWidth (string fileName)
{
string[] lines = File.ReadAllLines(fileName);
int length = lines[0].Length;
foreach (string s in lines)
{
if (s.length != Length)
{
return false;
}
}
return true;
}
Once you get that lines variable, you can access any character as though they were in a matrix. Like char c = lines[3][1];. However, there is no hard guarantee that all lines are the same length. You could pad them to be the same length as the longest one, if you so wanted.
Also,
"how would I query to get a list of all columns that contain a space character for ALL rows (for example)"
You could try this:
public bool CheckIfAllCharactersInAColumnAreTheSame (string[] lines, int colIndex)
{
char c = lines[0][colIndex];
try
{
foreach (string s in lines)
{
if (s[colIndex] != c)
{
return false;
}
}
return true;
}
catch (IndexOutOfRangeException ex)
{
return false;
}
}
Since it's not clear where you're have difficulty exactly, here are a few pointers.
Reading the file as strings, one per line:
string[] lines = File.ReadAllLines("filename.txt");
Obtaning a jagged array (a matrix) of characters from the lines (this step seems unnecessary since strings can be indexed just like character arrays):
char[][] charMatrix = lines.Select(l => l.ToCharArray()).ToArray();
Example query: whether every character in column 0 is a 't':
bool allTs = charMatrix.All(row => row[0] == 't');