chillinOutMaxin
chillinOutMaxin

Reputation: 182

Finding and printing a value from 2 different lists using LINQ

I am having trouble understanding LINQ statements. I have to following code:

//All list are filled from a file//
if (DoctorList.Any(y => EpisodeList.Any(x => y.Debut == x.Story)))
{
   Year.Text = x.Year.ToString();
   Episode.Text = x.Title;
}
if (DoctorList.Any(y => CompanionList.Any(c => y.docNum == c.Doctor)))
{
   Companions.Items.Add(String.Format(c.Name + " (" + c.Actor + ")"));
}
if (CompanionList.Any(y => EpisodeList.Any(x => x.Story == y.Debut)))
{
   Companions.Items.Add(String.Format(x.Title + " (" + x.Year + ")"));
   Companions.Items.Add("");
}

I have 2 issues. 1 - I need to print the value of the object found. For example, in the following code I need to get a value stored inside object x called Year and the value Title.

if (DoctorList.Any(y => EpisodeList.Any( x => y.Debut == x.Story))) 
{
    Year.Text = x.Year.ToString();
    Episode.Text = x.Title;
}

2 - is with the second and third if statements. There could be 30 different companions that should be added to the listBox but with those if statements, I would only find one. I am still learning how to use LINQ statements and I am not sure how I would get multiple values with one.

Upvotes: 0

Views: 65

Answers (2)

TheGeneral
TheGeneral

Reputation: 81523

Its kind of hard to understand what you are doing or wanting to achieve

But you need to reverse your logic i think so you can access the episode

In regards to you first question, if you just want to access the first episode found you could just do something like this

var episode = EpisodeList.FirstOrDefault(x => DoctorList.Any(y => y.Debut == x.Story));
if (episode != null)
{
   Debug.WriteLine($"year = {episode.Year}, Title = {episode.Title}");
}

In regards to your second question, if you have multiple occurrences you can just do a where, and select into a list, do the formatting on the fly and add it do the Companions List (what ever that might be)

var namesActors = EpisodeList.Where(x => DoctorList.Any(y => y.docNum == x.Doctor))
   .Select(x => $"{x.Name} ({x.Actor})")
   .ToList();

foreach (var value in namesActors)
   Companions.Items.Add(value);

var titleYears = EpisodeList.Where(x => DoctorList.Any(y => y.Debut == x.Story))
   .Select(x => $"{x.Title} ({x.Year})")
   .ToList();

foreach (var value in titleYears)
   Companions.Items.Add(value);

Upvotes: 2

symbiont
symbiont

Reputation: 1562

I would first use LINQ to filter for the relevant objects.

If you know that there is at most 1 object that matches, then you can use SingleOrDefault which returns the object if it is found or the default value which is null for objects:

Episode e = EpisodeList.SingleOrDefault(x => DoctorList.Any(y => y.Debut == x.Story))
if (e != null) // found episode
{
    Year.Text = e.Year.ToString();
    Episode.Text = e.Title;
}

If there can be multiple results you can use Where:

List<Episode> es = EpisodeList.Where(x => DoctorList.Any(y => y.Debut == x.Story)).ToList();
foreach (Episode e in es)
{
    Companions.Items.Add(String.Format(e.Title + " (" + e.Year + ")"));
    Companions.Items.Add("");
}

You can also use the following syntax, which is easier to write (although a little less readable)

var es = EpisodeList.Where(x => DoctorList.Any(y => y.Debut == x.Story));
foreach (var e in es)
{
    Companions.Items.Add(String.Format(e.Title + " (" + e.Year + ")"));
    Companions.Items.Add("");
}

Extra info In LINQ to SQL lazy evaluation would be used, so "ToList()" forces it to get the result from the database immediately. This is instead of waiting for the result to be used (in this case by iterating it with the foreach loop). But you can ignore this difference if you are not using LINQ to SQL.

Upvotes: 1

Related Questions