Cross Product Example

CSharp · Console

/Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
					
public class Program
{
	public class ProductVariantModel
	{
		public string Name { get; set; }

		public string Options { get; set; }
	}

	public class CreateModel
	{
		public string Name { get; set; }
		public IList<ProductVariantModel> Variants { get; set; }
	}
	
    public class ProductVariantOption {
		public string Name { get; set; }
	}
	
	private static ProductVariantOption BuildModel(string[] modelParts) {
		if (modelParts.Length == 1) {
			return new ProductVariantOption {
				Name = modelParts.Single()
			};	
		}
		
		var baseName = modelParts.First();
		var variantParts = string.Join('/', modelParts.Skip(1));
		return new ProductVariantOption {
			Name = $"{baseName}-{variantParts}"
		}; 
	}
	
	public static IList<ProductVariantOption> GetVariants(CreateModel model) {
		// Prepare all possible variables from the model in advance
		var allVariables = model.Variants.Select(v => v.Options.Split(",")).ToArray();
		
		var initialParts = new List<string[]> { new[] { model.Name } };
		// Generate cross product for every subsequent variant with initial list as a seed
		// Every iteration of aggregate produces all possible combination of models with the new variant
		var allModels = allVariables.Aggregate(initialParts, (variantsSoFar, variableValues) =>
			variantsSoFar
		        .SelectMany(variant => variableValues.Select(variableValue => variant.Append(variableValue).ToArray()))
				.ToList()
		);
			
		// Map all lists of model parts into ProductVariantOption
		return allModels.Select(BuildModel).ToList();
	}
	
	public static void Main()
	{
		var testModel = new CreateModel {
			Name = "Jean",
			Variants = new List<ProductVariantModel> {
				new ProductVariantModel {
					Name = "Color",
					Options = "Grey,Black"
				},
				new ProductVariantModel {
					Name = "Size",
					Options = "X,XL"
				},
				new ProductVariantModel {
					Name = "Stretch",
					Options = "Low,High,Mid"
				}
			}
		};
		
		
  	    var productOptions = GetVariants(testModel);
        
		Console.WriteLine(string.Join("\n", productOptions.Select(it => it.Name)));
	}
}
;