2

I have the following classes:

public class SerializedDelegate
{
    public List<GOEntry> goEntries = new List<GOEntry>();
}
public class GOEntry
{
    public string go;
    public List<MBEntry> mbEntries = new List<MBEntry>();
}
public class MBEntry
{
    public string mb;
    public List<MethodEntry> methodsEntries = new List<MethodEntry>();
}
public class MethodEntry
{
    public string method;
}

And this data:

var sd = new SerializedDelegate();
var eGo1 = new GOEntry { go = "Player1" };
var eGo2 = new GOEntry { go = "Player2" };
var eMb1 = new MBEntry { mb = "MB1" };
var eMb2 = new MBEntry { mb = "MB2" };
var eM1 = new MethodEntry { method = "target1" };
var eM2 = new MethodEntry { method = "target2" };
var eM3 = new MethodEntry { method = "target3" };
var eM4 = new MethodEntry { method = "target4" };
eMb1.methodsEntries.Add(eM1);
eMb1.methodsEntries.Add(eM2);
eMb2.methodsEntries.Add(eM3);
eMb2.methodsEntries.Add(eM4);
eGo1.mbEntries.AddRange(new[] { eMb1, eMb2 });
eGo2.mbEntries.Add(eMb1);
sd.goEntries.AddRange(new[] { eGo1, eGo2 });

What I'm trying to do - is print them in the following form:

     Player1: MB1.target1
     Player1: MB1.target2
     Player1: MB2.target3
     Player1: MB2.target4
     Player2: MB1.target1
     Player2: MB1.target2

I have printed them using foreach loops:

foreach (var goEntry in sd.goEntries) {
    foreach (var mbEntry in goEntry.mbEntries) {
        foreach (var methodEntry in mbEntry.methodsEntries)
            Console.WriteLine(goEntry.go + ": " + mbEntry.mb + "." + methodEntry.method);
    }
}

But I want to do it in a LINQ way - I want to construct a LINQ structure that corresponds to how I want to print them - so that I only need one foreach loop (so the length of the constructed enumerable is the number of total methods - in this case, 6).

I started like this - but no idea how to proceed further:

var entries = sd.goEntries
    .Select(g => new
    {
        GO = g.go,
        MBs = g.mbEntries,
        Methods = g.mbEntries.SelectMany(e => e.methodsEntries)
    });

Eventually, those method entries will be in a popup - so that's why I need a structure, that through out I could easily tell which MBEntry belongs to which GOEntry, and what MethodEntry belongs to which MBEntry.

Sorry if I wasn't clear enough - if that's the case, please say so.

Thanks.

3 Answers 3

1
var entries = from goEntry in sd.goEntries
              from mbEntry in goEntry.mbEntries
              from methodEntry in mbEntry.methodsEntries
              select new { goEntry.go, mbEntry.mb, methodEntry.method };

You can output entries this way:

 foreach(var entry in entries)
    Console.WriteLine("{0}: {1}.{2}", entry.go, entry.mb, entry.method);
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you! - ahh, I missed that. Could you please post the long dotted linq extension methods format?
@vexe it will not be that beautiful, because you will need to use intermediate anonymous objects and SelectMany methods
ahh... which explains why I had troubles with it... It seems that I have to use the SQL format more often.
@SergeyBerezovskiy: You don't need any more anonymous objects than in your example, it just doesn't read anywhere near as well (see my answer for implementation).
@Chris I know, thats why I deleted my update. Anyway - I would go with query syntax here
1

It sounds like you want something like:

var lines = from goEntry in sd.goEntries
            from mbEntry in goEntry.mbEnties
            from methodEntry in mbEntry.methodsEntries
            select string.Format("{0}: {1}.{2}",
                                 goEntry.go, mbEntry.mb, methodEntry.method);

foreach (var line in lines)
{
    Console.WriteLine(line);
}

Or if you'd rather do the formatting later:

var entries = from goEntry in sd.goEntries
              from mbEntry in goEntry.mbEnties
              from methodEntry in mbEntry.methodsEntries
              select new { goEntry, mbEntry, methodEntry };

foreach (var entry in entries)
{
    Console.WriteLine("{0}: {1}.{2}", entry.goEntry.go,
                      entry.mbEntry.mb, entry.methodEntry.method);
}

... or capture the individual values to format (goEntry.go etc) as per Sergey's answer. Lots of different approaches :)

Comments

1

Others have given nicer looking answers but since you asked in an other comment for the method version of it I present it here:

sd.goEntries.SelectMany(
    ge=>ge.mbEntries.SelectMany(
        mb=>mb.methodsEntries.Select(
            me=>new {me.method, mb.mb, ge.go}
        )
    )
)

It is much harder to see what this is doing than the query syntax style as demonstrated by two other current answers.

1 Comment

Thanks for the answer - yea, it's very cumbersome.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.