2010-11-02 71 views
0

请帮助我在其中一个场景中,我被困住了。Linq交叉连接查询嵌套列表

它是这样的。

  1. 使用PropertyGrid动态创建的列表和列表中的字段(内部表)列表。

    BindingList<Table> table = new BindingList<Table>();   
    [Serializable] 
    [TypeConverter(typeof(TableConverter))] 
    public class Table { 
    private string _name = string.Empty; 
    private HeaderCollection _hc = new HeaderCollection(); 
    private BindingList<Fields> _fc = new BindingList<Fields>(); 
    public Guid key; 
    public Table() { 
        key = Guid.NewGuid(); 
    } 
    
    
    [DisplayName("Table Fields"), Editor(typeof(FieldCollectionEditor), 
    typeof(UITypeEditor))] 
    public BindingList<Fields> Fields { 
        get { return _fc; } 
        set { _fc = value; } 
    } 
    [DisplayName("Table Header")] 
    public HeaderCollection Headers { 
        get { return _hc; } 
        set { _hc = value; } 
    } 
    
    
    [DisplayName("Table Name")] 
    public string Name { 
        get { return _name; } 
        set { _name = value; } 
        } 
    } 
    
  2. Field类定义

    [Serializable] 
    public class Fields { 
    private string _name = string.Empty; 
    public Guid Key; 
    private List<string> _value = new List<string>(); 
    
    
    [Browsable(false)] 
    public List<string> Value { 
        get { return _value; } 
        set { _value = value; } 
    }  
    
    
    public Fields() { 
        Key = Guid.NewGuid(); 
    } 
    
    
    [DisplayName("Field Name")] 
    public string Name { 
        get { return _name; } 
        set { _name = value; } 
    } 
    
    
    [DisplayName("Map")] 
    public bool Map { 
        get; 
        set; 
        } 
    } 
    
  3. Field类包含字符串列表,以容纳一个或多个值。

我的问题是:需要交叉连接所有值beloging到表中的所有字段并以表格格式显示数据。 我已经使用了这个查询,但是这不起作用,因为它会逐个提取值,而我需要一次性从所有字段的所有值进行coross连接。

var result = table.SelectMany(
    tbl => tbl.Fields.SelectMany(
     f => f.Value.Select(v => new { i = v }))); 

例如 可以说:

F1 has Value11 
F2 has Value21 
F3 has Value31 and Value 32 
F4 has Value41, Value42 and Value43 

结果应该是在此格式为每个表和所有字段值。

Value11 Value21 Value 31 Value 41 
Value11 Value21 Value 31 Value 42 
Value11 Value21 Value 31 Value 43 
Value11 Value21 Value 32 Value 41 
Value11 Value21 Value 32 Value 42 
Value11 Value21 Value 32 Value 43 

让我详细说明这一点。例如,如果我们有

List<string> master = new List<string>(); 
List<string> child = new List<string>(); 
List<string> child1 = new List<string>(); 
List<string> child2 = new List<string>(); 
and a Linq query to fetch out 

var q = from m in master 
     from c1 in child1 
     from c in child 
     from c2 in child2 
     select new { m, c, c1, c2 }; 

我正好需要这样写上面的查询获取了字段值,但字段动态生成的问题,因此它们的值里面,所以我需要某种recussive方法或linq过程来获得上面示例中提供的结果。

回答

2

你似乎有一个结构,清除所有其他细节:

  • 表具有字段集合
  • 字段有值

的集合,并希望有一个结果是是所有的价值观跨越所有领域。我会(使用两个查询来获得这两个循环)跨越自身的各个领域取得的所有值的集合开始:

var values = from v in (from f in Table.Fields select f.Values) 
      select v; 

,然后进行连接:

var res = from v in values 
      from f in Table.Fields 
      select new { 
      Field = f, 
      Value = v 
      }; 
+0

这为我场的x值,而不是我需要的价值X值(跨所有领域)。 – user885412 2010-11-03 03:48:15

+0

@Buzzy:你的回答应该作为对问题的修改来完成(因为它正在扩大/改进问题,而不是回答)。第二:我必须考虑这一点(想到递归),第三:Eric Lippert已经解决了我的问题:http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/计算笛卡尔的产品与LINQ.aspx – Richard 2010-11-03 08:58:24

+0

谢谢理查德,我要通过埃里克利珀博客,我会回来,这并不能解决我的问题 – user885412 2010-11-03 10:34:49

0

感谢您即时回应 我试过你的方法,但仍然没有以tabluar格式获取值。让我再次清楚细节。

咱们说

Field1 has Value11 
Field2 has Value21 
Field3 has Value31 and Value32 
Field4 has Value41, Value42 and Value43 

所有这些领域都属于单表。

现在交叉连接后,结果应该如下所示。

Value11 Value21 Value31 Value41 
Value11 Value21 Value31 Value42 
Value11 Value21 Value31 Value43 
Value11 Value21 Value32 Value41 
Value11 Value21 Value32 Value42 
Value11 Value21 Value32 Value43 

....... 
------ 

etc. 

感谢

嗡嗡

1

这应包括在第一篇文章的主/子样本:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var listofInts = new List<List<int>>(3); 
     listofInts.Add(new List<int>{1, 2, 3}); 
     listofInts.Add(new List<int> { 4,5,6 }); 
     listofInts.Add(new List<int> { 7,8,9,10 }); 

     var temp = CrossJoinLists(listofInts); 
     foreach (var l in temp) 
     { 
      foreach (var i in l) 
       Console.Write(i + ","); 
      Console.WriteLine(); 
     } 
    } 

    private static IEnumerable<List<T>> CrossJoinLists<T>(IEnumerable<List<T>> listofObjects) 
    { 
     var result = from obj in listofObjects.First() 
        select new List<T> {obj}; 

     for (var i = 1; i < listofObjects.Count(); i++) 
     { 
      var iLocal = i; 
      result = from obj in result 
        from obj2 in listofObjects.ElementAt(iLocal) 
        select new List<T>(obj){ obj2 }; 
     } 

     return result; 
    } 
}