Home > Mobile >  C# Foreach Usage
C# Foreach Usage

Time:04-19

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>
    }
}
  • Related