I want to use 2 variables and iterate over different objects with a single line foreach, If I wanted to do it with python I could use as follows.
<div>
@(for firstSong, secondSong Model.Web.OrderBy(p=>p.ListOrder()) )
{
<div >
<div >
firstSong.Name
</div>
<div >
secondSong.Name
</div>
</div>
}
</div>
<div>
but I want to do the same thing with c#, how can I do it?
@foreach(var song in Model.Web.OrderBy(p=>p.ListOrder())
{
<div >
<div >
song.Name
</div>
<div >
song.Name
</div>
</div>
}
</div>
CodePudding user response:
In older C# you'd possibly do this with a plain for
that jumps 2:
var arr = Model.Web.OrderBy(p=>p.ListOrder()).ToArray();
@for(int x = 0; x < arr.Length; x =2)
{
<div >
<div >
@arr[x].Name
</div>
@if(x 1 < arr.Length){
<div >
@arr[x 1].Name
</div>
}
</div>
}
</div>
You could use some LINQ to juggle your collection into tuples of song pairs, if your C# is modern enough to have Chunk (.net6 )
@foreach(var array in Model.Web.OrderBy(p=>p.ListOrder()).Chunk(2))
{
<div >
<div >
@array[0].Name
</div>
@if(arr.Length > 1){
<div >
@array[1].Name
</div>
}
</div>
}
</div>
There are other ways of doing it in older LINQ, such as projecting to include the index of each item, using a Where to take only the evens and Zipping them together with only the odds, or grouping them by the divide-by-2 of the index, but it gets a bit ugly:
@foreach(var array in Model.Web.OrderBy(p=>p.ListOrder()).Select((o,i)=>new{o,i}).GroupBy(at => at.i/2, at=> at.o), (k,g)=>g.ToArray())
...
<div >
<div >
@array[0].Name
</div>
@if(array.Length > 1){
<div >
@array[1].Name
</div>
}
</div>
It'd perhaps be better to write your own Chunk/lift it from the .net source
CodePudding user response:
If you're not using .NET 6 and can't take advantage of .Chunk
(as in the other answer), you could perhaps get an IEnumerator<Song>
and iterate through that manually:
@{
IEnumerator<Song> songEnumerator = Model.Web.OrderBy(p => p.ListOrder()).GetEnumerator();
while (songEnumerator.MoveNext())
{
<div >
<!-- handle the first song -->
<div >
@songEnumerator.Current.Name
</div>
<!-- try and get the second item -->
@if (@songEnumerator.MoveNext())
{
<div >
@songEnumerator.Current.Name
</div>
}
</div>
}
}