【问题标题】:Concatenating result sets连接结果集
【发布时间】:2011-01-02 22:21:24
【问题描述】:

我正在尝试为目录中的每个产品生成所有可能的产品选项/值组合的列表。每个产品可以有不定数量的选项,每个选项可以有不定数量的值。

例如,假设我有一件衬衫,选项/值是颜色(红色、黄色、蓝色)、尺寸(s、m、l)和材料(棉、尼龙、混纺)。我想生成一个如下所示的列表:

red, s, cotton
red, s, nylon
red, s, blend
red, m, cotton
red, m, nylon
red, m, blend
red, l, cotton
red, l, nylon
red, l, blend
yellow, s, cotton
yellow, s, nylon
yellow, s, blend
yellow, m, cotton
yellow, m, nylon
yellow, m, blend
yellow, l, cotton
yellow, l, nylon
yellow, l, blend
blue, s, cotton
blue, s, nylon
blue, s, blend
blue, m, cotton
blue, m, nylon
blue, m, blend
blue, l, cotton
blue, l, nylon
blue, l, blend

我知道理论上这会产生很多结果,但实际上大多数产品只有两个或三个选项,每个选项有两个或三个值。

我正在使用 C#,但任何类型的代码示例都会非常有帮助。非常感谢您的任何建议!

【问题讨论】:

  • 对于其中一些答案,您使用的 .Net 版本很重要。使用 Tuple 的需要 4.0,任何使用 LINQ 的都需要 3.5+。

标签: c# combinations


【解决方案1】:

样板材料:

public class Color
{
    private readonly string _color;

    public Color(string color)
    {
        _color = color;
    }

    public override string ToString()
    {
        return _color;
    }
}

public class Size
{
    private readonly string _size;

    public Size(string size)
    {
        _size = size;
    }

    public override string ToString()
    {
        return _size;
    }
}

public class Material
{
    private readonly string _material;

    public Material(string material)
    {
        _material = material;
    }

    public override string ToString()
    {
        return _material;
    }
}

相关部分:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var colors = new List<Color>() { new Color("Red"), 
                                             new Color("Yellow"), 
                                             new Color("Blue") };

            var sizes = new List<Size>() { new Size("S"), 
                                           new Size("M"), 
                                           new Size("L") };

            var materials = new List<Material>() { new Material("Cotton"),
                                                   new Material("Nylon"),
                                                   new Material("Blend") };

            var products = from c in colors
                           from s in sizes
                           from m in materials
                           select new { Color = c, Size = s, Material = m };


            foreach (var p in products)
            {
                Console.WriteLine("{0}, {1}, {2}", p.Color, p.Size, p.Material);
            }
            Console.ReadKey(true);
        }
    }
}

【讨论】:

  • 虽然不是我正在寻找的确切解决方案,但这让我足够了解它。我从所有提供的答案中遇到的主要区别是我并不总是使用三组选项 - 有时有两个,有时有四个甚至五个。这些选项是从数据库中读取的,我事先不知道如何输入它们。无论如何,通过一些额外的黑客攻击,这个答案让我到达了那里。非常感谢!
【解决方案2】:
var results =   from c in colours
                from s in sizes
                from m in materials
                select Tuple.Create(c, s, m);

或者你可以在最后一行创建一个匿名类型:

select new { Colour = c, Size = s, Material = m };

【讨论】:

  • 不错的答案......但是,应该指出Tuple.Create 只是.NET4。
【解决方案3】:

可以这么简单:

public class Product
{
  public string Colour { get; set; }
  public string Size { get; set; }
  public string Material { get; set; }
}

IList<Product> products = new List<Product>();
foreach (string colour in colours)
{
  foreach (string size in sizes)
  {
    foreach (string material in materials)
    {
      products.Add(new Product 
      {
        Colour = colour,
        Size = size,
        Material = material
      });
    }
  }
}

其中colourssizesmaterials 是值的字符串数组。这是你所期待的吗?

【讨论】:

    【解决方案4】:

    这实际上是交叉连接,而不是串联。

    您可以在 C# 中使用 LINQ 或嵌套的 foreach 循环非常简单地做到这一点。 LINQ 方式看起来很容易。假设颜色、尺寸和面料都已经作为集合存在于您的代码中。

    from color in colors
    from size in sizes
    from fabric in fabrics
    select new {
        color,
        size,
        fabric
    }
    

    【讨论】:

      【解决方案5】:

      同时考虑:

      public enum Color    {Red, Yellow, Blue};
      public enum Size     {S, M, L};
      public enum Material {Cotton, Nylon, Blend};
      public class Product
      {
         public Color    color;
         public Size     size;
         public Material material;
      }
      
      List<Product> products = new List<Product>();
      
      int numColors    = Enum.GetValues(typeof(Color)).Length;
      int numSizes     = Enum.GetValues(typeof(Size)).Length;
      int numMaterials = Enum.GetValues(typeof(Material)).Length;
      
      for(int i = 0; i < numColors; i++)
         for(int j = 0; k < numSizes; j++)
             for(int k = 0; k < numMaterials; k++)
             {
                Product p  = new Product();
                p.color    = (Color)i;
                p.size     = (Size)j;
                p.material = (Material)k;
                products.Add(p);
             }
      

      【讨论】:

      • 这也需要对 for 循环中的每个枚举赋值进行强制转换。例如。 p.color = (颜色)i;
      • @Pabuc -- 很着急,不记得究竟如何计算 Enum 项目。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多