Linq запрос на перекрестное соединение для вложенного списка - PullRequest
0 голосов
/ 02 ноября 2010

Пожалуйста, помогите мне в одном из сценариев, где я застрял.

Это так.

  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. Определение класса поля

    [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. Поле класса содержит список строк для хранения одного или нескольких значений.

Моя проблема заключается в следующем: необходимо перекрестно соединить все значения, относящиеся ко всем полям таблицы, и отобразить данные в табличном формате. Я использовал этот запрос, но он не работает, поскольку он выбирает значения одно за другим, вместо этого мне нужно соединение 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 };

Мне точно нужно написать приведенный выше запрос, чтобы получить значения полей, но проблема в том, что поля генерируются динамически, и поэтому значения внутри него, поэтому мне нужен какой-то рекурсивный метод или процедура linq для получения результата, как указано в примере выше.

Ответы [ 3 ]

2 голосов
/ 02 ноября 2010

У вас, похоже, есть структура, удаляющая все остальные детали:

  • Таблица имеет коллекцию полей
  • Поле имеет коллекцию значений

И хотите получить результат, когда все значения пересекают все поля. Я бы начал с получения коллекции всех значений по всем полям самостоятельно (используя два запроса для получения обоих циклов):

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
          };
1 голос
/ 01 ноября 2011

Это должно охватывать ваш основной / дочерний образец в первом посте:

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;
    }
}
0 голосов
/ 02 ноября 2010

Спасибо за ваш немедленный ответ. Я попробовал ваш подход, но все еще не получил значения в формате 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.  

Спасибо

Buzzy

...