2
\$\begingroup\$

I am fairly new to programming and I am having difficulty modulating the following code.

The program reads a file, selects certain requirements, and displays them. I have tried to use passing arrays as arguments or functions as indicated in my textbook. I have been using examples such as int getAges(int array[], integer).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Project_2_practice
{
    class Program
    {
       static void Main(string[] args)
        {

            //Parsing data into memory
            string content;
            using (StreamReader reader = new StreamReader(File.Open("Data.txt", FileMode.Open)))
            {
                content = reader.ReadToEnd();
            }
            string[] rows = content.Split('\n'); //Each row is on a new line
            string[][] table = new string[rows.Length][];
            for (int i = 0; i < rows.Length; table[i] = rows[i].Split(','), i++) ;



     //selecting information

            int[] districts = new int[rows.Length];
            int[] ages = new int[rows.Length];


            for (int i = 0; i < rows.Length; i++)
            {
                districts[i] = int.Parse(table[i][3]);
                ages[i] = int.Parse(table[i][0]);
            } 
                //Analyzing selected information
                foreach (int district in districts.Distinct().OrderBy(x => x))
                Console.WriteLine("District {0} has {1} resident(s)", district, districts.Count(x => x == district));
                Console.WriteLine("Ages 0-18 : {0} resident(s)", ages.Count(x => x < 18));
                Console.WriteLine("Ages 18-30 : {0} resident(s)", ages.Count(x => x >= 18 && x <= 30));
                Console.WriteLine("Ages 31-45 : {0} resident(s)", ages.Count(x => x >= 31 && x <= 45));
                Console.WriteLine("Ages 46-64 : {0} resident(s)", ages.Count(x => x >= 46 && x <= 64));
                Console.WriteLine("Ages >=65 : {0} resident(s)", ages.Count(x => x >= 65));
        }
    }
}
\$\endgroup\$
3
\$\begingroup\$

Here's how I would do it.

Update: I included a description of my code this time based on comments.

First, reading a file into a variable so that each line of the file is its own element in an array is super easy with File.ReadAllLines(...). But I don't feel like using a variable for that is necessary here, so I immediately start using the array by using the Select(...) method. I'm using Select here to create an anonymous type (That's the return new { ... } part).

var data = File.ReadAllLines(@"c:\temp\data.txt").Select (f => 
{
    var split = f.Split(',');
    return new { 
        Age = int.Parse(split[0]),
        District = split[3]
    };
});

At this point, I've got a type-safe collection of "data" that I can work with. That's important, and very useful. For example..

var byDistrict = data.GroupBy (d => d.District);

In the line above, I've grouped the data by District. Grouping is, in my opinion, almost always better than using Distinct.

The rest of the code is very similar to your original code, except my code avoids the need to have the age reports within a loop.

foreach (var district in byDistrict)
{
    Console.WriteLine("District {0} has {1} resident(s)", district.Key, district.Count());

}

Console.WriteLine("Ages 0-18 : {0} resident(s)", data.Count(x => x.Age < 18));
Console.WriteLine("Ages 18-30 : {0} resident(s)", data.Count(x => x.Age >= 18 && x.Age <= 30));
Console.WriteLine("Ages 31-45 : {0} resident(s)", data.Count(x => x.Age >= 31 && x.Age <= 45));
Console.WriteLine("Ages 46-64 : {0} resident(s)", data.Count(x => x.Age >= 46 && x.Age <= 64));
Console.WriteLine("Ages >=65 : {0} resident(s)", data.Count(x => x.Age >= 65));
\$\endgroup\$
  • \$\begingroup\$ would you please explain your code? Code Only answers are frowned upon on Code Review. \$\endgroup\$ – Malachi Nov 6 '13 at 15:55
  • \$\begingroup\$ Sorry. Fairly new to Code Review. But I really love this site. \$\endgroup\$ – Alex Dresko Nov 6 '13 at 16:06
  • \$\begingroup\$ it's all good, thank you for editing your answer. +1 \$\endgroup\$ – Malachi Nov 6 '13 at 16:32
1
\$\begingroup\$

I feel as though you are looking at how to really understand the code and how to separate it out into functions and still have all the variables working and all that. I rewrote it a bit to show how to use different functions with and without return values, with variables passed in, using global variables, and passing in variables by reference. Take a look.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;


namespace Project_2_practice
{
    class Program
    {
        static string[][] table;
        static void Main(string[] args)
        {

            //Parsing data into memory
            string[] rows = ReadLines("Data.txt");
            table = new string[rows.Length][];
            PopulateTable(rows);

            //selecting information
            int[] districts = new int[rows.Length];
            int[] ages = new int[rows.Length];
            PopulateArrays(ref districts, ref ages, rows.Length);


            //Analyzing selected information
            DisplayResults(districts, ages);
        }
        /// <summary>
        /// Read file into memory
        /// </summary>
        /// <param name="file">string filepath</param>
        /// <returns>array of lines in file</returns>
        private static string[] ReadLines(string file)
        {
            return File.ReadAllLines(file);
        }
        /// <summary>
        /// Populates a table with split values from the string
        /// </summary>
        /// <param name="rows">array of strings to split</param>
        private static void PopulateTable(string[] rows)
        {
            for (int i = 0; i < rows.Length; table[i] = rows[i].Split(','), i++) ;
        }
        /// <summary>
        /// Populates 2 arrays by reference with values from the table variable
        /// </summary>
        /// <param name="districts">int array</param>
        /// <param name="ages">int array</param>
        /// <param name="length">int length of table</param>
        private static void PopulateArrays(ref int[] districts, ref int[] ages, int length)
        {
            for (int i = 0; i < length; i++)
            {
                districts[i] = int.Parse(table[i][3]);
                ages[i] = int.Parse(table[i][0]);
            }
        }
        /// <summary>
        /// Writes values to console for displaying results
        /// </summary>
        /// <param name="districts">int array of districts</param>
        /// <param name="ages">int array of ages</param>
        private static void DisplayResults(int[] districts, int[] ages)
        {
            foreach (int district in districts.Distinct().OrderBy(x => x))
            {
                Console.WriteLine("District {0} has {1} resident(s)", district, districts.Count(x => x == district));
            }
            Console.WriteLine("Ages 0-18 : {0} resident(s)", ages.Count(x => x < 18));
            Console.WriteLine("Ages 18-30 : {0} resident(s)", ages.Count(x => x >= 18 && x <= 30));
            Console.WriteLine("Ages 31-45 : {0} resident(s)", ages.Count(x => x >= 31 && x <= 45));
            Console.WriteLine("Ages 46-64 : {0} resident(s)", ages.Count(x => x >= 46 && x <= 64));
            Console.WriteLine("Ages >=65 : {0} resident(s)", ages.Count(x => x >= 65));
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ thank you very much for this insight! this is exactly what I wanted to see if it was possible, however your code doesn't compile, it seems that the errors marked in visual studio are that static string[] contentLines; static string[][] table; are not used \$\endgroup\$ – hec Nov 6 '13 at 15:15
  • \$\begingroup\$ You are right, I am going to edit my answer to fix those. I erroneously created a local variable named table as well as the global one so that caused the code to fail. Also, I just removed the contentLines var as it's not needed. \$\endgroup\$ – Kemo Sabe Nov 6 '13 at 15:24
  • 1
    \$\begingroup\$ thank you I see how everything comes together, this is pretty interesting. Thanks for making me understand Kemo Sabe! \$\endgroup\$ – hec Nov 6 '13 at 15:47
  • 1
    \$\begingroup\$ Glad to help :) \$\endgroup\$ – Kemo Sabe Nov 6 '13 at 15:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.