1
class C
{
    public int Value;
    public int[] Items;
}

var data = new C[] { new C() { Value = 1, Items = new int[] { 1, 2, 3 } },
                            new C() { Value = 10, Items = new int[] { 10, 20, 30 } } };

I'd like to combine Value with value of each Item for each instance of C in data, so the result should be tuples of {1,1}, {1,2}, {1,3}, {10,10}, {10,20}, {10,30}

I already have a procedural solution:

var list = new List<Tuple<int, int>>();
foreach (var c in data)
    foreach (var item in c.Items)
        list.Add(Tuple.Create(c.Value, item));

But I'd like to know how can I write this in LINQ.

Axarydax
  • 16,353
  • 21
  • 92
  • 151
  • I suspect SelectMany will be able to solve this, as per this question: http://stackoverflow.com/questions/4283866/different-ways-of-using-selectmany – Axarydax Jun 25 '14 at 13:43

4 Answers4

2

Something like this?

var list = 
    (from c in data
    from item in c.Items
    select Tuple.Create(c.Value, item)).ToList();
Dennis_E
  • 8,751
  • 23
  • 29
1

You can create Tuple based on each item and its value and then use SelectMany to flatten that like:

List<Tuple<int, int>> list = data.Select(mainItem => mainItem.Items
                                .Select(item =>
                                        Tuple.Create(mainItem.Value, item)))
                                 .SelectMany(r => r)
                                 .ToList();

You will get:

enter image description here

Habib
  • 219,104
  • 29
  • 407
  • 436
1

Got it with this overload of SelectMany - the code was adapted from the example in the documentation:

  var result = data.SelectMany(p=>p.Items,(p,item)=>new {Value=p.Value,Item=item});
Axarydax
  • 16,353
  • 21
  • 92
  • 151
0

SelectMany with a factory Func for creating the tuples

List<Tuple<int, int>> flattenedDataList = data
            .SelectMany(c => c.Items, (c, i) => Tuple.Create(c.Value, i))
            .ToList();
Joseph King
  • 5,089
  • 1
  • 30
  • 37