'C# Foreach Usage

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 class="item">
           <div class="row">
              firstSong.Name
           </div>
           <div class="row2">
              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 class="item">
   <div class="row">
      song.Name
   </div>
   <div class="row2">
      song.Name
   </div>
</div>
}
</div>


Solution 1:[1]

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 class="item">
   <div class="row">
      @arr[x].Name
   </div>
   @if(x+1 < arr.Length){
     <div class="row2">
      @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 class="item">
   <div class="row">
      @array[0].Name
   </div>
   @if(arr.Length > 1){
     <div class="row2">
      @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 class="item">
       <div class="row">
          @array[0].Name
       </div>
       @if(array.Length > 1){
         <div class="row2">
          @array[1].Name
         </div>
       }
    </div>

It'd perhaps be better to write your own Chunk/lift it from the .net source

Solution 2:[2]

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 class="item">
            <!-- handle the first song -->
            <div class="row">
                @songEnumerator.Current.Name
            </div>

            <!-- try and get the second item -->
            @if (@songEnumerator.MoveNext())
            {
                <div class="row2">
                    @songEnumerator.Current.Name
                </div>
            }

        </div>
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 DiplomacyNotWar