Alexander
Alexander

Reputation: 20224

Repeat list endlessly (Zip a finite list with an Infinite repeating sequence)

UserList is a list of dictionaries, like:

[
  {Name:"Alex",Age:25},
  {Name:"Peter",Age:35},
  {Name:"Muhammad",Age:28},
  {Name:"Raul",Age:29}
]

RowColorList is a list of colors: [#bcf,#fc0]

The new UserList should contain one RowColor for every name, taken in sequence from RowColorList:

[
  {Name:"Alex",Age:25,RowColor:#bcf},
  {Name:"Peter",Age:35,RowColor:#fc0},
  {Name:"Muhammad",Age:28,RowColor:#bcf},
  {Name:"Raul",Age:29,RowColor:#fc0}
]

I tried the following code:

UserList.Zip(RowColorList,(user,color) => user.Add("RowColor",color))

With this code, the new UserList will only contain as many entries as are in RowColorList. I would like him to start from the beginning of RowColorList again, whenever the available colors are used up. How?

Upvotes: 4

Views: 494

Answers (2)

StuartLC
StuartLC

Reputation: 107247

You can create a function to return an infinite enumerable of Color / string (or whatever the type of RowColor is), by using yield return as a lazy generator:

public IEnumerable<Color> InfiniteColors()
{
    while (true)
    {   
        foreach (var color in RowColors)
        {
            yield return color;
        }
    }
}

This can then be used with any of the Linq IEnumerable extension methods such as Zip.

UserList.Zip(InfiniteColors(),(user,color) => user.Add("RowColor",color))

Edit - Explanation

The reason why InfiniteColors doesn't hang is because the state machine will yield back to the caller after each result, and Zip will terminate on the first enumerable to complete, which is because the other collection being zipped is finite (i.e. UserList)

Obviously you shouldn't try and Zip the InfiniteColors enumerable with itself, nor should you try and materialize InfiniteColors, i.e. don't call InfiniteColors.ToList() or such :-):

Upvotes: 7

Thomas C. G. de Vilhena
Thomas C. G. de Vilhena

Reputation: 14565

Something like this should do the trick:

var i = 0;
var l = RowColorList.Count;
UserList.ForEach(user => user.Add("RowColor", RowColorList[(i++) % l]));

The % operator will guarantee "cyclic" access to the RowColorList.

Upvotes: 3

Related Questions