Reputation: 13
I'm working on a homework problem for my computer science class. A cities census data is on a text file holding records for its citizens. Each line will have four fields(age, gender, marital status, and district) of different data types separated by a comma. For example, 22, F, M, 1.
How should I approach this? My thoughts are that I should use two 1D arrays, one for age and one for district. I need to be able to later count how many people are in each district, and how many people are in different age groups for the whole city.
How do I read each line and get the info I want into each array?
edit** This is what I've managed to do so far. I'm trying to separate my data from fields into four different arrays. This is where I'm stuck.
FileStream fStream = new FileStream("test.txt", FileMode.Open, FileAccess.Read);
StreamReader inFile = new StreamReader(fStream);
string inputRecord = "";
string[] fields;
int[] ageData = new int[1000];
string[] genderData = new string[1000];
string[] maritalData = new string[1000];
int[] districtData = new int[1000];
inputRecord = inFile.ReadLine();
while (inputRecord != null)
{
fields = inputRecord.Split(',');
int i = 0;
ageData[i] = int.Parse(fields[0]);
genderData[i] = fields[1];
maritalData[i] = fields[2];
districtData[i] = int.Parse(fields[3]);
i++;
inputRecord = inFile.ReadLine();
}
edit 2**
First question, I've decided to use the below code to find out how many citizens are in each district of the census data.
for (int x = 1; x <= 22; x++)
for (int y = 0; y < districtData.Length; y++)
if (districtData[y] == x)
countDist[x]++;
for (int x = 1; x <= 22; x++)
Console.WriteLine("District " + x + " has " + countDist[x] + " citizens");
In my .Writeline
when x
reaches two digits it throws off my columns. How could I line up my columns better?
Second question, I am not quite sure how to go about separating the values I have in ageData
into age groups using an if statement.
Upvotes: 0
Views: 1289
Reputation: 150108
It sounds like each of the four fields have something in common... they represent a person surveyed by the census. That's a good time to use a class along the lines of
public class Person
{
public int Age { get; set; }
public string Gender { get; set; }
public string MaritalStatus { get; set; }
public int District { get; set; }
}
Then, just read in all of the lines from the text file (if it's small, it's fine to use File.ReadAllLines()), and then create an instance of Person for each line in the file.
You can create a
List<Person> people;
to hold the Person instances that you parse from the text file.
Since the lines appear to be separated by commas, have a look at String.Split().
UPDATE
The attempt in your edit is pretty close. You keep creating a new i
and initializing it to 0. Instead, initialize it outside your loop:
int i = 0;
while (inputRecord != null)
{
fields = inputRecord.Split(',');
Also you may want to trim excess spaces of of your input. If the fields are separated with ", " rather than just "," you will have excess spaces in your fields.
genderData[i] = fields[1].Trim();
maritalData[i] = fields[2].Trim();
Upvotes: 2
Reputation: 3697
public static class PersonsManager
{
public static PersonStatistics LoadFromFile(string filePath)
{
var statistics = new PersonStatistics();
using (var reader = new StreamReader(filePath))
{
var separators = new[] { ',' };
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (string.IsNullOrWhiteSpace(line))
continue; //--malformed line
var lParts = line.Split(separators, StringSplitOptions.RemoveEmptyEntries);
if (lParts.Length != 4)
continue; //--malformed line
var person = new Person
{
Age = int.Parse(lParts[0].Trim()),
Gender = lParts[1].Trim(),
MaritalStatus = lParts[2].Trim(),
District = int.Parse(lParts[3].Trim())
};
statistics.Persons.Add(person);
}
}
return statistics;
}
}
public class PersonStatistics
{
public List<Person> Persons { get; private set; }
public PersonStatistics()
{
Persons = new List<Person>();
}
public IEnumerable<Person> GetAllByGender(string gender)
{
return GetByPredicate(p => string.Equals(p.Gender, gender, StringComparison.InvariantCultureIgnoreCase));
}
//--NOTE: add defined queries as many as you need
public IEnumerable<Person> GetByPredicate(Predicate<Person> predicate)
{
return Persons.Where(p => predicate(p)).ToArray();
}
}
public class Person
{
public int Age { get; set; }
public string Gender { get; set; }
public string MaritalStatus { get; set; }
public int District { get; set; }
}
Usage:
var statistics = PersonsManager.LoadFromFile(@"d:\persons.txt");
var females = statistics.GetAllByGender("F");
foreach (var p in females)
{
Console.WriteLine("{0} {1} {2} {3}", p.Age, p.Gender, p.MaritalStatus, p.District);
}
I hope it helps.
Upvotes: 0
Reputation: 2382
How about this?
List<string[]> o = File.ReadAllLines(@"C:\TestCases\test.txt").Select(x => x.Split(',')).OrderBy(y => y[0]).ToList();
Each person is a string array in the list. Each property is a index in the array eg: age is first. The above code reads all lines comma delimits them orders them by age and adds them to the list.
Upvotes: 0