Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a dictionary with keys representing elements from a list

Tags:

c#

linq

I want to create a Dictionary where the Keys are representing elements from a List. Each list element has to be present in this dictionary.

Example:
A movie has a list of actors.

Now I want a list of movies the actor acted in. If the movies have more than one actor, each actor should have the movie in their own list.

I have a data strucuture like this:

public class MovieData
{
    public List<string> Actors { get; set;}
    public string Title { get; set; }
    public DateTime ReleaseDate { get; set; }
    public string FilePath { get; set; }
}

A small example to illustrate this:

var movie1 = new MovieData { 
  Title  = "Movie1", 
  Actors = new List<string> { "Bob Smith", "Alice Stevens"}};

var movie2 = new MovieData { 
  Title  = "Movie2", 
  Actors = new List<string> { "Alice Stevens"}};

var movie3 = new MovieData { 
  Title  = "Movie3", 
  Actors = new List<string> { "John Doe" }};

The desired result should look like this:

Alice Stevens => { "Movie1", "Movie2" }
Bob Smith     => { "Movie1" }
John Doe      => { "Movie3" }

I came up with the following code, but it only pays attention to the first actor in the list (FirstOrDefault()). So other actors in the list are ignored.

var actorMovieList = movieDataList
  .ToLookup(movie => movie
                       .Actors
                       .FirstOrDefault(), movie => movie);

How can I include the other actors in the list? I have to iterate through the actor list inside of the lambda, but I don't know how.

like image 823
titanoxid Avatar asked Feb 13 '26 17:02

titanoxid


2 Answers

You can try SelectMany to flatten the initial List<List<string>> into

{actor, title}

records and then put GroupBy to group them by actor into required dictionary:

var result = movieDataList
  .SelectMany(movie => movie
     .Actors
     .Select(actor => new {    // from now we have flat cursor of
        actor = actor,         // {actor, title} records
        title = movie.Title
      }))
  .GroupBy(record => record.actor,  // ... which we group by actor: 
           record => record.title)  // actor and movies (s)he played in 
  .ToDictionary(group => group.Key, // or ToLookUp() 
                group => group.ToList());
like image 59
Dmitry Bychenko Avatar answered Feb 16 '26 06:02

Dmitry Bychenko


You can flatten the movieDataList first (using SelectMany method) into collection of actors and movie titles and then use ToLookup method with this collection. It allows you to include all authors in the final result

var movieDataList = new List<MovieData>() { movie1, movie2, movie3 };

var result = movieDataList
    .SelectMany(m => m.Actors
        .Select(a => new
        {
            Actor = a,
            Movie = m.Title
        }))
    .ToLookup(pair => pair.Actor, pair => pair.Movie);

foreach (var item in result)
{
    Console.WriteLine($"{item.Key} {string.Join(",", item)}");
}

The output will be the following

enter image description here

like image 34
Pavel Anikhouski Avatar answered Feb 16 '26 05:02

Pavel Anikhouski



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!