Reputation: 42185
I have a list of Channels
var blocks = new List<Block>();
foreach (var channel in ChannelsCollection)
{
var ch = channel.ChannelCollectionItems.Select(item => new Channel
{
Id = channel.Id,
Delay = item.Delay,
Trigger = item.Trigger,
Restore = item.Restore,
}).ToList();
blocks.Add(new Block { Id = index++ , Channels = ch});
}
This results in a list of Blocks
, each of which contains a list of Channels
.
e.g.
Block1 Block2 Block3 Block4
Channel1 Channel1 Channel1 Channel1
Val1 Val1 Val1 Val1
Val2 Val2 Val2 Val2
Val3 Val3 Val3 Val3
Channel2 Channel2 Channel2 Channel2
Val1 Val1 Val1 Val1
Val2 Val2 Val2 Val2
Val3 Val3 Val3 Val3
Channel3 Channel3 Channel3 Channel3
Val1 Val1 Val1 Val1
Val2 Val2 Val2 Val2
Val3 Val3 Val3 Val3
I need to pivot this list so that I have a list of Channels
that contain each Block
for that channel.
e.g.
Channel1
Block1 Block2 Block3
Val1 Val1 Val1
Val2 Val2 Val2
Val3 Val3 Val3
Channel2
Block1 Block2 Block3
Val1 Val1 Val1
Val2 Val2 Val2
Val3 Val3 Val3
Channel3
Block1 Block2 Block3
Val1 Val1 Val1
Val2 Val2 Val2
Val3 Val3 Val3
Is there a quick way, (e.g. with LINQ) to do this?
Edit
Channel
and Block
are defined as:
public class Channel
{
public int? Id { get; set; }
public string Delay { get; set; }
public string Trigger { get; set; }
public string Restore { get; set; }
}
public class Block
{
public int Id { get; set; }
public List<Channel> Channels { get; set; }
}
Upvotes: 2
Views: 1741
Reputation: 42185
This turned out to be the solution:
public class ChannelRowCell
{
public string Name { get; set; }
public string Delay { get; set; }
public string Trigger { get; set; }
public string Restore { get; set; }
}
public class ChannelRow
{
public int Id { get; set; }
public List<ChannelRowCell> Cells { get; set; }
}
public static class DigiChannelsExtensions
{
public static List<ChannelRow> GetRows(this List<DigiChannelsVM> digiChannelsVms)
{
var blocks = (from vm in digiChannelsVms
let ch = vm.ChannelCollectionItems.Select(item => new
{
vm.Id,
Type = item.Types.EnumDataItems.FirstOrDefault(xx => xx.IsSet).Description,
Delay = item.Delay.Value.ToString(),
Trigger = item.Trigger.Value == 0 ? "+" : "-",
Restore = item.Restore.GetSelectedEnumItems().FirstOrDefault().Description == "Restore" ? "Y" : "N",
}).ToList()
select new { Id = vm.Id.Value, Channels = ch }).ToList();
var channelRows = new List<ChannelRow>();
//for (var i = 0; i < blocks[0].Channels.Count; i++)
for (var i = 0; i < blocks[0].Channels.Count; i++)
{
var channelRow = new ChannelRow { Cells = new List<ChannelRowCell>(), Id = i+1 };
foreach (var cc in blocks.Select(block => block.Channels[i]))
{
channelRow.Cells.Add(new ChannelRowCell
{
Delay = cc.Delay,
Name = cc.Type,
Restore = cc.Restore,
Trigger = cc.Trigger,
});
}
channelRows.Add(channelRow);
}
return channelRows;
}
}
Upvotes: 0
Reputation: 50114
Try something like
var channels = blocks
.SelectMany(b => b.Channels.Select(c => new { b, c }))
.GroupBy(p => p.c.Id)
.Select(g => new { Channel = g.First().c, Blocks = g.Select(p => p.b) });
As others have pointed out, your Channel
class doesn't have anywhere to store a sequence of Block
s, so this returns a sequence of anonymous objects with a Channel
called Channel
and an IEnumerable<Block>
called Blocks
.
Note that it also compares Channel
s by Id
, since they don't appear to be comparable otherwise. If your Channel
s are inconsistent between Block
s, this just takes the Channel
from the first Block
.
Upvotes: 2
Reputation: 32561
Try this:
var r = blocks
.GroupBy(b => b.Channels.Select(c => c))
.Select(g => new { Channel = g.Key, Blocks = g.Select(b1 => b1) });
Upvotes: 1