2013-09-16 2 views
2

Я искал без успеха аналогичную ситуацию следующим образом.Неравномерные списки размеров для слияния

У меня есть два списка, список A и список B.
Список A состоит из 10 объектов, созданных из ClassA, который содержит только строки.
Список B состоит из 100 объектов, созданных из класса B, которые содержат только десятичные числа.

Список A - информация заголовка.
Список В - информация о данных.

Взаимосвязь между этими двумя списками есть:

Row 1 of list A corresponds to rows 1-10 of list B. 
Row 2 of list A corresponds to rows 11-20 of list B. 
Row 3 of list A corresponds to rows 21-30 of list B. 

и т.д .........

Как совместить эти два списка, так что, когда я их отображения на консоли пользователь увидит строку заголовка, за которой сразу следуют соответствующие 10 строк данных.

Приносим извинения, если раньше был дан ответ.

+0

Таким образом, список A будет * всегда * содержать 10 объектов, а List B будет * всегда * содержать 100 объектов? –

+0

Я читаю из текстового файла, и количество объектов в A может меняться. – greg

+0

@greg вы имели в виду 10 объектов в списке B для каждого 1 объекта в списке A? –

ответ

1

Хорошо, что должно работать. Дайте мне знать, если у меня что-то не так.

List<ClassA> listA = GetListA()// ... 
List<ClassB> listB = GetListA()// ... 


if(listB.Count % listA.Count != 0)  
     throw new Exception("Unable to match listA to listB"); 

var datasPerHeader = listB.Count/listA.Count; 

for(int i = 0; i < listA.Count;i++) 
{ 
    ClassA header = listA[i]; 
    IEnumerable<ListB> datas = listB.Skip(datasPerHeader*i).Take(datasPerHeader); 
    Console.WriteLine(header.ToString()); 
    foreach(var data in datas) 
    { 
      Console.WriteLine("\t{0}", data.ToString()); 
    } 
} 
+0

+1 на вашем модном контроле ... Я оставил его как упражнение на плакате, но в основном дословно. – tostringtheory

+0

Спасибо за вашу помощь, это прекрасно работает. Мой опыт программирования ограничен, и я мог лучше понять ваш пример. Интерфейс IEnumerable - это то, что я раньше не использовал, но скоро. Я все еще ищу способы объединения списков, содержащих разные типы. – greg

+0

круто, рад это слышать. 'IEnumerable' - это интерфейс, который обобщает все коллекции, например. все массивы, списки, последовательности, хэш-таблицы, словари в .net реализуют IEnumerable, что означает, что они являются последовательностью/набором некоторых элементов и могут быть перечислены. –

1

Вот код, который должен выполнить ваш запрос - Я собираюсь найти ссылку на расширение раздела, как я не могу найти его в своем коде больше:

void Main() 
{ 
    List<string> strings = Enumerable.Range(1,10).Select(x=>x.ToString()).ToList(); 
    List<decimal> decimals = Enumerable.Range(1,100).Select(x=>(Decimal)x).ToList(); 

    var detailsRows = decimals.Partition(10) 
           .Select((details, row) => new {HeaderRow = row, DetailsRows = details}); 

    var headerRows = strings.Select((header, row) => new {HeaderRow = row, Header = header}); 

    var final = headerRows.Join(detailsRows, x=>x.HeaderRow, x=>x.HeaderRow, (header, details) => new {Header = header.Header, Details = details.DetailsRows}); 
} 

public static class Extensions 
{ 
    public static IEnumerable<List<T>> Partition<T>(this IEnumerable<T> source, Int32 size) 
    { 
     for (int i = 0; i < Math.Ceiling(source.Count()/(Double)size); i++) 
      yield return new List<T>(source.Skip(size * i).Take(size)); 
    } 
}  

Этот метод Partition является один что делает черновую работу ...

А вот ссылка на статью - LINK

EDIT 2

здесь лучше Код для метода Main() ... Бросился ответить и забыл мозг:

void Main() 
{ 
    List<string> strings = Enumerable.Range(1,10).Select(x=>x.ToString()).ToList(); 
    List<decimal> decimals = Enumerable.Range(1,100).Select(x=>(Decimal)x).ToList(); 

    var detailsRows = decimals.Partition(10); 

    var headerRows = strings; //just renamed for clarity from other code 

    var final = headerRows.Zip(detailsRows, (header, details) => new {Header = header, Details = details}); 
} 
+0

BTW, я использую LinqPad для создания моего примеры, поэтому вы должны иметь возможность скопировать/вставить это и запустить его в режиме программы C#. – tostringtheory

0

Самый простой способ может быть что-то вроде этого:

var listA = new List<string>() { "A", "B", "C", ... } 
var listB = new List<decimal>() { 1m, 2m, 3m, ... } 
double ratio = ((double)listA.Count)/listB.Count; 
var results = 
    from i in Enumerable.Range(0, listB.Count) 
    select new { A = listA[(int)Math.Truncate(i * ratio)], B = listB[i] }; 

Или беглом синтаксисом:

double ratio = ((double)listA.Count)/listB.Count; 
var results = Enumerable.Range(0, listB.Count) 
    .Select(i => new { A = listA[(int)Math.Truncate(i * ratio)], B = listB[i] }); 

Конечно, если вы знаете вы всегда будете иметь 10 пунктов в listB для каждого элемента в listA, вы можете упростить это:

var results = 
    from i in Enumerable.Range(0, listB.Count) 
    select new { A = listA[i/10], B = listB[i] }; 

Или беглом синтаксисом:

var results = Enumerable.Range(0, listB.Count) 
    .Select(i => new { A = listA[i/10], B = listB[i] }); 

Это возвращает результирующий набор, как

{ { "A", 1 }, 
    { "A", 2 }, 
    { "A", 3 } 
    .., 
    { "A", 10 }, 
    { "B", 11 }, 
    { "B", 12 }, 
    { "B", 13 }, 
    ... 
    { "B", 20 }, 
    { "C", 21 }, 
    ... 
    { "J", 100 } 
} 
1

Это должно быть довольно прямо вперед, если я что-то не хватает.

var grouped = ListA.Select((value, index) => 
    new { 
    ListAItem = value, 
    ListBItems = ListB.Skip(index * 10).Take(10) 
    }) 
    .ToList(); 

Возврат анонимного типа, через который вы можете пройти.

foreach (var group in grouped) 
{ 
    Console.WriteLine("List A: {0}", group.Name); 
    foreach (var listBItem in group.ListBItems) 
    { 
    Console.WriteLine("List B: {0}", listBItem.Name); 
    { 
} 
Смежные вопросы