'join 2 lists and create one to many relationship [closed]

Is it possible to join 2 lists and create one to many relationship?

For example,

list 1:
{"High", "Med", "Low"}

list 2:
{"Submitted", "In Progress", "Draft", "Rejected"}

final list, I will have values like this:

{
{"High", "Submitted"}, {"High", "In Progress"},{"High", "Draft"}, {"High", "Rejected"},
{"Med", "Submitted"}, {"Med", "In Progress"},{"Med", "Draft"}, {"Med", "Rejected"},
{"Low", "Submitted"}, {"Low", "In Progress"},{"Low", "Draft"}, {"Low", "Rejected"}
}


Solution 1:[1]

Not sure if this is what you are looking for, but you can use Select and SelectMany to create the final List of KeyVaulePair.

        var list1 = new List<string>() { "High", "Medium", "Low" };
        var list2 = new List<string>() { "Submitted", "In-Progress", "Draft", "Rejected" };
        
        var joined = list1.SelectMany(val1 => list2.Select(val2 => new KeyValuePair<string, string>(val1, val2)));
        foreach(var res in joined) 
        {
            Console.WriteLine(res.Key + "," + res.Value);
        }

If you want to use imperative style of coding, then just create 2 for loops

Solution 2:[2]

It seems, that you are looking for a Cartesian Join, you can do it with a help of Linq:

  var list1 = new List<string>() { 
    "High", "Medium", "Low" };

  var list2 = new List<string>() { 
    "Submitted", "In-Progress", "Draft", "Rejected" };
  
  // I've combined values as named tuple: (string first, string second)
  // but you can use anonymous class, or just concat string strings 
  var joined = list1
    .SelectMany(item1 => list2.Select(item2 => (first: item1, second: item2)));
    .ToList();

Let's have a look:

  Console.Write(string.Join(Environment.NewLine, joined));

Outcome:

(High, Submitted)
(High, In-Progress)
(High, Draft)
(High, Rejected)
(Medium, Submitted)
(Medium, In-Progress)
(Medium, Draft)
(Medium, Rejected)
(Low, Submitted)
(Low, In-Progress)
(Low, Draft)
(Low, Rejected)

Solution 3:[3]

LINQ method syntax for joins is pretty ugly and even counterintuitive, IMHO; query syntax looks much nicer/easier to read:

from s in list1
from t in list2
select new { s, t }

Or as a tuple:

from s in list1
from t in list2
select ( s, t )
            

Solution 4:[4]

If you want to do Cartesian product and want to store it in text-value pair then you can use List with SelectListItem. It will give you list with text-value pair.

var list1 = new List<string>() { "High", "Medium", "Low" };
var list2 = new List<string>() { "Submitted", "In-Progress", "Draft", "Rejected" };
List<SelectListItem> list3 = new List<SelectListItem>();
   foreach (string str in list1)
   {
      foreach(string str2 in list2)
      {
         list3.Add(new SelectListItem()
         { Text = str, Value = str2 });
      }
   }

Solution 5:[5]

You can use the join method from LINQ:

List<(string,string)> joined = list1.Join(list2, x => true, y => true, (x,y) => (x,y)).ToList();

The second and third parameter are selectors for list1 and list2. If both are the same, a joined value will be created. If we give the same constant value for both selectors, the joining condition is always fulfilled and hence all possible pairs are created.

Online demo: https://dotnetfiddle.net/JaK6ff

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Pratik Bhattacharya
Solution 2 Dmitry Bychenko
Solution 3 Caius Jard
Solution 4 Karnav Modi
Solution 5