-3

I have a list of attribute values that look like this:

public class AttributeOption
{
   public Guid Id { get; set; }
   public string Name { get; set; }
}

public class MyAttribute
{
   public Guid Id { get; set; }
   public string Name { get; set; }
   public List<AttributeOption> Options { get; set; } = new List<AttributeOption>();
}

I have a list of attributes i.e. var attributes = new List<MyAttribute>(); and the list contains three sets of attributes e.g. color, size and gender. Each attribute has its options. For example, color has red, white and blue options. Size has small, medium and large and finally gender has male and female.

How do I generate a cartesian product of all these attributes? I should end up with:

Red-Small-Male
Red-Small-Female
Red-Medium-Male
...
White-Small-Male
White-Small-Female
...
Sam
  • 26,817
  • 58
  • 206
  • 383
  • I couldn’t get it to work with nested loops so I figured I need to use LINQ – Sam Feb 08 '23 at 19:12
  • @user09938 They’re not enumerations for a reason as they’re user defined and more can be added by users in the future. That’s why they also have their own IDs – Sam Feb 08 '23 at 19:19
  • 2
    @user09938 `foreach` loops are great, but if there can be a different number of attribute types, it begins to be tricky. – NetMage Feb 08 '23 at 19:30

1 Answers1

0

From this answer and this later answer, you can use an extension method to generate the Cartesian Product of an arbitrary number of sequences:

public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences) =>
    sequences.Aggregate(Enumerable.Empty<T>().AsSingleton(),
                        (accumulator, sequence) => accumulator.SelectMany(prodSoFar => sequence.Select(prodSoFar.Append)));
public static IEnumerable<T> AsSingleton<T>(this T item) => new[] { item };

Using this extension method, you can use LINQ to generate your desired answer.

var ans = attributes.Select(a => a.Options.Select(o => o.Name))
                    .CartesianProduct()
                    .Select(s => String.Join("-", s))
                    .ToList();
NetMage
  • 26,163
  • 3
  • 34
  • 55