Getting the best record from a file

I have a file with the following text inside

mimi, m, 70
tata, f, 60
bobo, m, 100
soso, f, 30

I've done reading from file and many other methods and functions, but how can I get the best male name and its grade according to the degree.

here is the code i wrote. Hope it doesn't take too long

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

namespace practice_Ex
{
    class Program
    {
        public static int[] ReadFile(string FileName, out string[] Name, out char[] Gender)
        {
            Name = new string[1];
            int[] Mark = new int[1];
            Gender = new char[1];
            if (File.Exists(FileName))
            {
                FileStream Input = new FileStream(FileName, FileMode.Open, FileAccess.Read);
                StreamReader SR = new StreamReader(Input);
                string[] Current;
                int Counter = 0;
                string Str = SR.ReadLine();
                while (Str != null)
                {
                    Current = Str.Split(',');
                    Name[Counter] = Current[0];
                    Mark[Counter] = int.Parse(Current[2]);
                    Gender[Counter] = char.Parse(Current[1].ToUpper());
                    Counter++;
                    Array.Resize(ref Name, Counter + 1);
                    Array.Resize(ref Mark, Counter + 1);
                    Array.Resize(ref Gender, Counter + 1);
                    Str = SR.ReadLine();
                }
            }
            return Mark;
        }

        public static int MostFreq(int[] M, out int Frequency)
        {
            int Counter = 0;
            int Frequent = 0;
            Frequency = 0;
            for (int i = 0; i < M.Length; i++)
            {
                Counter = 0;
                for (int j = 0; j < M.Length; j++)
                    if (M[i] == M[j])
                        Counter++;
                if (Counter > Frequency)
                {
                    Frequency = Counter;
                    Frequent = M[i];
                }
            }
            return Frequent;
        }

        public static int Avg(int[] M)
        {
            int total = 0;
            for (int i = 0; i < M.Length; i++)
                total += M[i];
            return total / M.Length;
        }

        public static int AvgCond(char[] G, int[] M, char S)
        {
            int total = 0;
            int counter = 0;
            for (int i = 0; i < G.Length; i++)
                if (G[i] == S)
                {
                    total += M[i];
                    counter++;
                }
            return total / counter;
        }

        public static int BelowAvg(int[] M, out int AboveAvg)
        {
            int Bcounter = 0;
            AboveAvg = 0;
            for (int i = 0; i < M.Length; i++)
            {
                if (M[i] < Avg(M))
                    Bcounter++;
                else
                    AboveAvg++;
            }
            return Bcounter;
        }

        public static int CheckNames(string[] Name, char C)
        {
            C = char.Parse(C.ToString().ToLower());
            int counter = 0;
            string Str;
            for (int i = 0; i < Name.Length - 1; i++)
            {
                Str = Name[i].ToLower();
                if (Str[0] == C || Str[Str.Length - 1] == C)
                    counter++;
            }
            return counter;
        }

        public static void WriteFile(string FileName, string[] Output)
        {
            FileStream FS = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.Write);
            StreamWriter SW = new StreamWriter(FS);
            for (int i = 0; i < Output.Length; i++)
                SW.WriteLine(Output[i]);
        }

        static void Main(string[] args)
        {
            int[] Mark;
            char[] Gender;
            string[] Name;
            string[] Output = new string[8];
            int Frequent, Frequency, AvgAll, MaleAvg, FemaleAvg, BelowAverage, AboveAverage, NamesCheck;
            Mark = ReadFile("c:\\IUST1.txt", out Name, out Gender);
            Frequent = MostFreq(Mark, out Frequency);
            AvgAll = Avg(Mark);
            MaleAvg = AvgCond(Gender, Mark, 'M');
            FemaleAvg = AvgCond(Gender, Mark, 'F');
            BelowAverage = BelowAvg(Mark, out AboveAverage);
            NamesCheck = CheckNames(Name, 'T');
            Output [0]= "Frequent Mark = " + Frequent.ToString();
            Output [1]= "Frequency = " + Frequency.ToString();
            Output [2]= "Average Of All = " + AvgAll.ToString();
            Output [3]= "Average Of Males = " + MaleAvg.ToString();
            Output [4]= "Average Of Females = " + FemaleAvg.ToString();
            Output [5]= "Below Average = " + BelowAverage.ToString();
            Output [6]= "Above Average = " + AboveAverage.ToString();
            Output [7]= "Names With \"T\" = " + NamesCheck.ToString();
            WriteFile("c:\\Output.txt", Output);
        }
    }
}

      

+1


source to share


5 answers


Well, I like LINQ (update: excluded via comments) for queries, especially if I can do it without buffering the data (so I can handle a huge file efficiently). For example below (update: LINQ removed); note that using iterator ( yield return

) blocks makes this completely "lazy" - only one entry is stored in memory at a time.

It also shows a separation of concerns: one method is about reading the file line by line; one method relates to parsing a string into a typed data record; one (or more) method works with data (s) data.

using System;
using System.Collections.Generic;
using System.IO;

enum Gender { Male, Female, Unknown }
class Record
{
    public string Name { get; set; }
    public Gender Gender { get; set; }
    public int Score { get; set; }
}
static class Program
{
    static IEnumerable<string> ReadLines(string path)
    {
        using (StreamReader reader = File.OpenText(path))
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                yield return line;
            }
        }
    }
    static IEnumerable<Record> Parse(string path)
    {
        foreach (string line in ReadLines(path))
        {
            string[] segments = line.Split(',');
            Gender gender;
            switch(segments[1]) {
                case "m": gender = Gender.Male; break;
                case "f": gender = Gender.Female; break;
                default: gender = Gender.Unknown; break;
            }
            yield return new Record
            {
                Name = segments[0],
                Gender = gender,
                Score = int.Parse(segments[2])
            };
        }
    }
    static void Main()
    {
        Record best = null;
        foreach (Record record in Parse("data.txt"))
        {
            if (record.Gender != Gender.Male) continue;
            if (best == null || record.Score > best.Score)
            {
                best = record;
            }
        }

        Console.WriteLine("{0}: {1}", best.Name, best.Score);
    }
}

      



The advantage of writing things as iterators is that you can stream or buffering easily - for example, you can:

List<Record> data = new List<Record>(Parse("data.txt"));

      

and then manipulate data

all day (assuming it's not too big) - useful for lots of aggregates, mutating data, etc.

+2


source


This question asks how to find the maximum element by a certain criterion. Combine that with the Marc LINQ part and you're gone.



+1


source


In the real world, of course, these would be records in the database, and you would use a single SQL line to select the best record, that is:

SELECT Name, Score FROM Grade WHERE Score = MAX (Score)

(This returns more than one entry, where of course there is more than one best entry.) This is an example of using the correct tool for the job.

+1


source


I think the fastest and least code would be converting the txt to xml and then using Linq2Xml to select it. Here's the link.

Edit: This may be more than you would like to do. Another option is to create an AcademicRecord class that has properties for the person's name, etc. Then, when you read the file, add to the list for each line in the file. Then use sort to sort the list; the highest entry will then be first on the list. Here's the link.

0


source


Your assignment may have different requirements, but if you want to get the "best male name and grade" from the file you described, the compact way is:

public String FindRecord()
{
    String[] lines = File.ReadAllLines("MyFile.csv");
    Array.Sort(lines, CompareByBestMaleName);
    return lines[0];
}

int SortByBestMaleName(String a, String b)
{
    String[] ap = a.Split();            
    String[] bp = b.Split();
     // Always rank male higher
    if (ap[1] == "m" && bp[1] == "f") { return 1; }
    if (ap[1] == "f" && bp[1] == "m") { return -1; }
    // Compare by score
    return int.Parse(ap[2]).CompareTo(int.Parse(bp[2]));
}

      

Please note that this is not fast or reliable.

0


source







All Articles