0

I have a list of arrays written to a text file. Each array holds 7 items: The first item is the class date, and the following six items are the student IDs who where given a task on that date. I want to be able to scan through the list of arrays and write to a separate file the dates each student is chosen.

For example, if student 04 is selected multiple times the file will show on the fourth line the dates that student was given a task. I am trying to use a for each loop to scan through each line.

Example data of the list of arrays stored:

00/00/0000,02,04,05,06,07,08
11/11/1111,01,02,05,06,08,09
22/22/2222,02,03,05,06,07,08

What i want to achieve is studentId,taskDate (Multiple if student has done multiple tasks), like this:

01,11/11/1111
02,00/00/0000,11/11/1111,22/22/2222
03,22/22/2222
04,00/00/0000
05,00/00/0000,11/11/1111,22/22/2222
06,00/00/0000,11/11/1111,22/22/2222
07,00/00/0000,22/22/2222
08,00/00/0000,11/11/1111,22/22/2222

So far I read from the text file as follows

string readrecord = @"C:\classes\tasks\taskrecord.txt";

List<string> lines = File.ReadAllLines(readrecord).ToList();

foreach (var line in lines)
{
    string[] tasks= entries[1].Split(',');
    taskDate = tasks[0];
    stu1 = tasks[1];
    stu2 = tasks[2];
    stu3 = tasks[3];
    stu4 = tasks[4];
    stu5 = tasks[5];
    stu6 = tasks[6];
}

Now I am trying to scan the list and write taskDate to file if stu1 to stu6 is equal to specific student id:

string writeTaskDate = @"C:\classes\tasks\dateRecord.txt";

if(stu1 == 01||stu2 == 01||stu3 == 01||stu4 == 01||stu5 == 01||stu6 == 01)
{
 //--How do i add taskDate to end of Line 1 of "writeTaskDate"??
}

else If(stu1 == 02||stu2 == 02||stu3 == 02||stu4 == 02||stu5 == 02||stu6 == 02
{
 //--How do i add taskDate to end of Line 2 of "writeTaskDate"??
}

...and so on for each student i have an ID for. Any advice is appreciated.

2
  • sorry the format of the example didn't work out Commented May 24, 2017 at 22:34
  • you can use the edit button to change your post Commented May 24, 2017 at 22:38

2 Answers 2

1

This should work:

//Prep work/data structures
var students = new SortedDictionary<string, List<string>>();
Action<string, string> AddStudentTask = (student, taskDate) => {
    if (!students.ContainsKey(student))
        students.Add(student, new List<string>());

    students[student].Add(taskDate);
};

//Read existing data
string readrecord = @"C:\classes\tasks\taskrecord.txt";
var lines = File.ReadLines(readrecord).Select(l => l.Split(','));
foreach (var line in lines)
{
    AddStudentTask(line[1], line[0]);
    AddStudentTask(line[2], line[0]);
    AddStudentTask(line[3], line[0]);
    AddStudentTask(line[4], line[0]);
    AddStudentTask(line[5], line[0]);
    AddStudentTask(line[6], line[0]);
}

//Write new data
string writeTaskDate = @"C:\classes\tasks\dateRecord.txt";
using (var sw = new StreamWriter(writeTaskDate))
{
    foreach (var item in students)
    {
        sw.Write(item.Key);
        sw.Write(",");
        sw.WriteLine(String.Join(",", item.Value));
    }
}

But it's based on a dictionary. If you know all of your student IDs are numeric and sequential with few gaps, and you know about how many there are, you can do even better by using a List or Array instead of the Dictionary, where the List index corresponds to the Student ID/Key field from the dictionary.

Sign up to request clarification or add additional context in comments.

2 Comments

This is very similar to what I was going to suggest, only better written. (I like the lambda idea, never would have thought about it myself :-)) +1
Honestly, I'd normally probably make the lambda a private named method in the same class. But since I don't have class context from the question, this is a better from a "copy/paste into my existing method" standpoint. Also, IIRC, C# 7 has cleaner syntax for this.
0

Using some extension methods:

public static TRes CDR<T, TRes>(this IEnumerable<T> lines, Func<T, IEnumerable<T>, TRes> resultFunc) => resultFunc(lines.First(), lines.Skip(1));
public static string Join(this IEnumerable<string> strings, char sep) => String.Join(sep.ToString(), strings.ToArray());
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> rest, params T[] first) => first.Concat(rest);

you can abuse LINQ like so:

var ans = lines.SelectMany(s => s.Split(',').CDR((d, sids) => sids.Select(sid => new { date = d, id = sid }))).OrderBy(did => did.id)
             .GroupBy(did => did.id, (id, didg) => didg.Select(did => did.date).Prepend(id).Join(','));

or without extensions:

var ans = lines.SelectMany(s => { var ls = s.Split(','); return ls.Skip(1).Select(sid => new { date = ls[0], id = sid }); }).OrderBy(did => did.id)
             .GroupBy(did => did.id, (id, didg) => id+","+String.Join(",", didg.Select(did => did.date))).Dump();

But I wouldn't recommend it. Do this instead:

var res = new Dictionary<string, List<string>>();
foreach (var s in lines) {
    var ls = s.Split(',');
    var d = ls[0];
    foreach (var id in ls.Skip(1)) {
        if (res.ContainsKey(id))
            res[id].Add(d);
        else
            res[id] = new List<string> { d };
    }
}
var ans = new List<string>();
foreach (var id in res.Keys.OrderBy(k => k)) {
    ans.Add(id+","+String.Join(",", res[id]));
}

Then just output ans however you like. You could also just output each line when created in the last method instead of adding to ans.

5 Comments

I really hope you don't actually use variable names like these. Otherwise you will hate yourself 6 months from now when you need to understand what your code does.
I find them understandable for years. d is date. sid is StudentID. sids is StudentIDS. did is Date+ID. didg is Date+ID Group.
Personally, I never liked newspeak. What if the poor bastard that's going to do maintenance on your code is someone else? doesn't he or she deserve to understand this code?
After 40 years of programming, I don't think anyone calls what I do "new". In any case, a lot of (old) Unix experience and some unfortunate COBOL experience makes me prefer succinct expression to overly verbose names and comments. The LINQ lambda syntax is very advanced code, I don't think longer variable names would help anyone who can't understand it just be reading it.
newspeak is from George Orwell's 1984 book... you know, where they used shorted words to prevent the people from having complicated ideas... I get that back in the day you had to use abbreviations, but IMHO in today's world I will always prefer to spend a few more letters on variables and method names. Anyway, Kudos on hanging in for 40 years... I've only been a professional programmer for the last 17 years and it's not getting that much easier :-)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.