CSharp · Console
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)));
}
}