Alternating items in a collection











up vote
8
down vote

favorite












Is there any better way how to mix items in list? In my example: I want to sort list items as male, female, male, ... My solution is probably very time and resource demanding. Can I do it somehow with LINQ?



private List<Child> MixGender(List<Child> children)
{
List<Child> male = new List<Child>() { };
List<Child> female = new List<Child>() { };

male = children.Where(c => c.Sex == "male").ToList();
female = children.Where(c => c.Sex == "female").ToList();

int childrenCount = children.Count;
int indexMale = 0;
int indexFemale = 0;

children.Clear();

for (int i = 0; i < childrenCount; i++)
{
if (i % 2 == 1)
{
if (indexMale < male.Count)
{
children.Add(male[indexMale]);
indexMale++;
}
else
{
children.Add(female[indexFemale]);
indexFemale++;
}
}
else
{
if (indexFemale < female.Count)
{
children.Add(female[indexFemale]);
indexFemale++;
}
else
{
children.Add(male[indexMale]);
indexMale++;
}
}
}

return children;
}









share|improve this question




















  • 4




    Could you reframe your question and the requirements? You write about mixing items in lists but then about sorting... I'm very confused.
    – t3chb0t
    Nov 8 at 16:25






  • 1




    I am sorry, English is not my native language. Sorting and mixing is the same thing in this scenario. I would like have every another item different. So in this case 1: male, 2:female, 3:male, 4:female, 5:male etc. My algorithm is working, but I would like to know if it is possible to do it better and faster way. Of course there can be same items on the end- depending on items in List
    – Tomas Kanok
    Nov 8 at 17:48










  • I follow. It looks OK to me.
    – paparazzo
    Nov 8 at 17:50










  • ok, now it makes sense, thank you for clarifying this ;-)
    – t3chb0t
    Nov 8 at 17:50















up vote
8
down vote

favorite












Is there any better way how to mix items in list? In my example: I want to sort list items as male, female, male, ... My solution is probably very time and resource demanding. Can I do it somehow with LINQ?



private List<Child> MixGender(List<Child> children)
{
List<Child> male = new List<Child>() { };
List<Child> female = new List<Child>() { };

male = children.Where(c => c.Sex == "male").ToList();
female = children.Where(c => c.Sex == "female").ToList();

int childrenCount = children.Count;
int indexMale = 0;
int indexFemale = 0;

children.Clear();

for (int i = 0; i < childrenCount; i++)
{
if (i % 2 == 1)
{
if (indexMale < male.Count)
{
children.Add(male[indexMale]);
indexMale++;
}
else
{
children.Add(female[indexFemale]);
indexFemale++;
}
}
else
{
if (indexFemale < female.Count)
{
children.Add(female[indexFemale]);
indexFemale++;
}
else
{
children.Add(male[indexMale]);
indexMale++;
}
}
}

return children;
}









share|improve this question




















  • 4




    Could you reframe your question and the requirements? You write about mixing items in lists but then about sorting... I'm very confused.
    – t3chb0t
    Nov 8 at 16:25






  • 1




    I am sorry, English is not my native language. Sorting and mixing is the same thing in this scenario. I would like have every another item different. So in this case 1: male, 2:female, 3:male, 4:female, 5:male etc. My algorithm is working, but I would like to know if it is possible to do it better and faster way. Of course there can be same items on the end- depending on items in List
    – Tomas Kanok
    Nov 8 at 17:48










  • I follow. It looks OK to me.
    – paparazzo
    Nov 8 at 17:50










  • ok, now it makes sense, thank you for clarifying this ;-)
    – t3chb0t
    Nov 8 at 17:50













up vote
8
down vote

favorite









up vote
8
down vote

favorite











Is there any better way how to mix items in list? In my example: I want to sort list items as male, female, male, ... My solution is probably very time and resource demanding. Can I do it somehow with LINQ?



private List<Child> MixGender(List<Child> children)
{
List<Child> male = new List<Child>() { };
List<Child> female = new List<Child>() { };

male = children.Where(c => c.Sex == "male").ToList();
female = children.Where(c => c.Sex == "female").ToList();

int childrenCount = children.Count;
int indexMale = 0;
int indexFemale = 0;

children.Clear();

for (int i = 0; i < childrenCount; i++)
{
if (i % 2 == 1)
{
if (indexMale < male.Count)
{
children.Add(male[indexMale]);
indexMale++;
}
else
{
children.Add(female[indexFemale]);
indexFemale++;
}
}
else
{
if (indexFemale < female.Count)
{
children.Add(female[indexFemale]);
indexFemale++;
}
else
{
children.Add(male[indexMale]);
indexMale++;
}
}
}

return children;
}









share|improve this question















Is there any better way how to mix items in list? In my example: I want to sort list items as male, female, male, ... My solution is probably very time and resource demanding. Can I do it somehow with LINQ?



private List<Child> MixGender(List<Child> children)
{
List<Child> male = new List<Child>() { };
List<Child> female = new List<Child>() { };

male = children.Where(c => c.Sex == "male").ToList();
female = children.Where(c => c.Sex == "female").ToList();

int childrenCount = children.Count;
int indexMale = 0;
int indexFemale = 0;

children.Clear();

for (int i = 0; i < childrenCount; i++)
{
if (i % 2 == 1)
{
if (indexMale < male.Count)
{
children.Add(male[indexMale]);
indexMale++;
}
else
{
children.Add(female[indexFemale]);
indexFemale++;
}
}
else
{
if (indexFemale < female.Count)
{
children.Add(female[indexFemale]);
indexFemale++;
}
else
{
children.Add(male[indexMale]);
indexMale++;
}
}
}

return children;
}






c# collections






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 8 at 18:03









t3chb0t

33.6k744108




33.6k744108










asked Nov 8 at 16:18









Tomas Kanok

433




433








  • 4




    Could you reframe your question and the requirements? You write about mixing items in lists but then about sorting... I'm very confused.
    – t3chb0t
    Nov 8 at 16:25






  • 1




    I am sorry, English is not my native language. Sorting and mixing is the same thing in this scenario. I would like have every another item different. So in this case 1: male, 2:female, 3:male, 4:female, 5:male etc. My algorithm is working, but I would like to know if it is possible to do it better and faster way. Of course there can be same items on the end- depending on items in List
    – Tomas Kanok
    Nov 8 at 17:48










  • I follow. It looks OK to me.
    – paparazzo
    Nov 8 at 17:50










  • ok, now it makes sense, thank you for clarifying this ;-)
    – t3chb0t
    Nov 8 at 17:50














  • 4




    Could you reframe your question and the requirements? You write about mixing items in lists but then about sorting... I'm very confused.
    – t3chb0t
    Nov 8 at 16:25






  • 1




    I am sorry, English is not my native language. Sorting and mixing is the same thing in this scenario. I would like have every another item different. So in this case 1: male, 2:female, 3:male, 4:female, 5:male etc. My algorithm is working, but I would like to know if it is possible to do it better and faster way. Of course there can be same items on the end- depending on items in List
    – Tomas Kanok
    Nov 8 at 17:48










  • I follow. It looks OK to me.
    – paparazzo
    Nov 8 at 17:50










  • ok, now it makes sense, thank you for clarifying this ;-)
    – t3chb0t
    Nov 8 at 17:50








4




4




Could you reframe your question and the requirements? You write about mixing items in lists but then about sorting... I'm very confused.
– t3chb0t
Nov 8 at 16:25




Could you reframe your question and the requirements? You write about mixing items in lists but then about sorting... I'm very confused.
– t3chb0t
Nov 8 at 16:25




1




1




I am sorry, English is not my native language. Sorting and mixing is the same thing in this scenario. I would like have every another item different. So in this case 1: male, 2:female, 3:male, 4:female, 5:male etc. My algorithm is working, but I would like to know if it is possible to do it better and faster way. Of course there can be same items on the end- depending on items in List
– Tomas Kanok
Nov 8 at 17:48




I am sorry, English is not my native language. Sorting and mixing is the same thing in this scenario. I would like have every another item different. So in this case 1: male, 2:female, 3:male, 4:female, 5:male etc. My algorithm is working, but I would like to know if it is possible to do it better and faster way. Of course there can be same items on the end- depending on items in List
– Tomas Kanok
Nov 8 at 17:48












I follow. It looks OK to me.
– paparazzo
Nov 8 at 17:50




I follow. It looks OK to me.
– paparazzo
Nov 8 at 17:50












ok, now it makes sense, thank you for clarifying this ;-)
– t3chb0t
Nov 8 at 17:50




ok, now it makes sense, thank you for clarifying this ;-)
– t3chb0t
Nov 8 at 17:50










4 Answers
4






active

oldest

votes

















up vote
6
down vote



accepted










It looks like the core of your problem is taking two sequences and "interleaving" them, alternating elements for as long as possible, but allowing for the sequences to be different lengths. Your solution will definitely do that.



BUT. It would be cleaner if you were able to avoid building up a List element-by-element, and if possible also avoid manual index management. My rule of thumb is "If you never access a list by index, you'll never have index-related bugs."



One way to do this would be to use enumerators. Your algorithm could look something like this:



while enumerator A has elements:
yield an element from enumerator A
if enumeratorB has another element:
yield an element from enumerator B

while enumerator B has elements:
yield an element from enumerator B


With this approach, you don't even need to know how many elements there are; you simply "go until you're done".



If I were writing this code, I would probably write it as an extension method, and call it like this:





private List<Child> MixGender(List<Child> children)
{
return children.Where(c => c.Sex == "male")
.Interleave(children.Where(c => c.Sex == "female"))
.ToList();
}




/// <summary>
/// Mix the elements of the two sequences, alternating elements
/// one by one for as long as possible. If one sequence has more
/// elements than the other, its leftovers will appear at the
/// end of the mixed sequence.
/// </summary>
public static IEnumerable<T> Interleave<T>(
this IEnumerable<T> sequenceA,
IEnumerable<T> sequenceB,
)
{
var enumA = sequenceA.GetEnumerator();
var enumB = sequenceB.GetEnumerator();

// As long as there are elements in sequence A
while (enumA.MoveNext())
{
// Take an element from sequence A
yield return enumA.Current;

// And, if possible,
if (enumB.MoveNext())
{
// Take an element from sequence B
yield return enumB.Current;
}
}

// If there are any elements left over in sequence B
while (enumB.MoveNext())
{
// Take each of them
yield return enumB.Current;
}
}


As for the question of time/resource demands: Is the invocation of an extension method, and handling of the enumerators more efficient then manual list creation and management? I would guess so, but I don't know, and I don't particularly care. I would be very confident in guessing that whatever performance gains you make by using one technique over the other will be dwarfed by, for example, the I/O operations your program is making. If (and only if) you notice performance degradation in your application, you should revisit the question with the help of a profiler.



Here is a demonstration comparing the behavior of your original implementation to the enumerator-based technique. They are almost the same but you may want to make some tweaks. It might be a good idea to adapt that demonstration into your unit test suite. Edit: As t3chb0t points out, it is also important to ensure your enumerators are Disposed, which this demo code fails to do.






share|improve this answer























  • this is a nice idea with Interleave and it would be even better if it took a single collection and a comparer to create the two other collections internally.
    – t3chb0t
    Nov 8 at 19:46










  • One complication that could arise (if we accept a key selector like child => child.Sex and not just a boolean filter) is the possibility of having N groups. That would be an interesting challenge to solve, but I would start to worry about over-engineering.
    – benj2240
    Nov 8 at 20:00










  • Challange accepted! I like over-engineering! (ok, as coding-sport, one can learn a lot - not in production) :-]
    – t3chb0t
    Nov 8 at 20:19










  • ok, this wasn't that difficult... take a look at my edit.
    – t3chb0t
    Nov 8 at 20:56


















up vote
9
down vote













Not a fan of LINQ, yet? Then look here... You could start by grouping Child by Sex into a new lookup, this would replace the two Wheres. In the next step you Zip them together and take one item from each collection at a time. You create from then new tiny collections that you finally flatten with SelectMany. No calculation necessary.



var groups = items.ToLookup(i => i.Sex);
var alternating =
groups["male"]
.Zip(groups["female"], (x, y) => new { x, y })
.SelectMany(t => t)
.ToList();


This will however require that both collections have the same length because Zip will go only as far as the shorter collection.





Some nice improvement to you method would be to make it work for any group of items. When you pass it a custom comparer you can GroupBy the items and iterate over each group until there is nothing left to yield. Since enumerators are disposable you need to make sure to dispose them properly at the end thus the finally block.



public static IEnumerable<T> Interleave<T>(this IEnumerable<T> source, IEqualityComparer<T> comparer)
{
var groups = source.GroupBy(x => x, comparer);
var enumerators = groups.Select(g => g.GetEnumerator()).ToList();
try
{
var any = false;
do
{
any = false;
foreach (var e in enumerators)
{
if (e.MoveNext())
{
any = true;
yield return e.Current;
}
}
} while (any);
}
finally
{
foreach (var e in enumerators)
{
e.Dispose();
}
}
}


An example usage could then look like this:



var innerComparer = StringComparer.OrdinalIgnoreCase;
var comparer = EqualityComparerFactory<Child>.Create
(
(x, y) => innerComparer.Equals(x.Sex, y.Sex),
obj => innerComparer.GetHashCode(obj.Sex)
);
var result = items.Interleave(comparer);





share|improve this answer



















  • 1




    instead of passing in an IEqualityComparer<T> how about a Func<T, TKey> and grouping off of that? Then you don't need EqualityComparerFactory and can still interleave over all the different values of a property.
    – C.M.
    Nov 8 at 21:52










  • @C.M. I think it would be a good idea to have both APIs because many linq extensions allow you to do it in the one or the other way with the comparer if you need something customized.
    – t3chb0t
    Nov 9 at 9:22


















up vote
8
down vote













My only comment is don't mutate the input and then return it.



private List<Child> MixGender(List<Child> children)


Return a fresh List<Child>.



Male and female should be enum.






share|improve this answer























  • I was just about to mention it ;-]
    – t3chb0t
    Nov 8 at 17:57










  • ok, now even I wonder why the downvote? This is an important point presented here.
    – t3chb0t
    Nov 8 at 18:05










  • I don't typically sweat the down votes. I have had way better answers than this get multiple down votes. If I am confused I will ask why but not to argue the down vote.
    – paparazzo
    Nov 8 at 19:52








  • 1




    I think mutating a list is acceptable, but agree it's cleaner to return a fresh list. It would depend on how big the list is and if using a lot of memory was a concern. (I find 99% of lists I deal with are less than 10 items.) -- I would add that if you are going to mutate the list then don't return the list, make the method void (or C# equivalent) to make it clear it's mutating.
    – Captain Man
    Nov 9 at 14:50












  • yes I noticed it too. How it is possible and why int is not mutating for example? I am not able to google something about "mutate c#"
    – Tomas Kanok
    Nov 9 at 15:52


















up vote
4
down vote













You can avoid building up an inner list in the method using yield returnin the following way:



private IEnumerable<Child> MixGender(List<Child> children)
{
List<Child> male = children.Where(c => c.Sex == "male").ToList();
List<Child> female = children.Where(c => c.Sex == "female").ToList();

int childrenCount = children.Count;
int indexMale = 0;
int indexFemale = 0;

for (int i = 0; i < childrenCount; i++)
{
if (i % 2 == 1)
{
if (indexMale < male.Count)
{
yield return male[indexMale];
indexMale++;
}
else
{
yield return female[indexFemale];
indexFemale++;
}
}
else
{
if (indexFemale < female.Count)
{
yield return female[indexFemale];
indexFemale++;
}
else
{
yield return male[indexMale];
indexMale++;
}
}
}
}





share|improve this answer





















    Your Answer





    StackExchange.ifUsing("editor", function () {
    return StackExchange.using("mathjaxEditing", function () {
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    });
    });
    }, "mathjax-editing");

    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "196"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














     

    draft saved


    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207240%2falternating-items-in-a-collection%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    6
    down vote



    accepted










    It looks like the core of your problem is taking two sequences and "interleaving" them, alternating elements for as long as possible, but allowing for the sequences to be different lengths. Your solution will definitely do that.



    BUT. It would be cleaner if you were able to avoid building up a List element-by-element, and if possible also avoid manual index management. My rule of thumb is "If you never access a list by index, you'll never have index-related bugs."



    One way to do this would be to use enumerators. Your algorithm could look something like this:



    while enumerator A has elements:
    yield an element from enumerator A
    if enumeratorB has another element:
    yield an element from enumerator B

    while enumerator B has elements:
    yield an element from enumerator B


    With this approach, you don't even need to know how many elements there are; you simply "go until you're done".



    If I were writing this code, I would probably write it as an extension method, and call it like this:





    private List<Child> MixGender(List<Child> children)
    {
    return children.Where(c => c.Sex == "male")
    .Interleave(children.Where(c => c.Sex == "female"))
    .ToList();
    }




    /// <summary>
    /// Mix the elements of the two sequences, alternating elements
    /// one by one for as long as possible. If one sequence has more
    /// elements than the other, its leftovers will appear at the
    /// end of the mixed sequence.
    /// </summary>
    public static IEnumerable<T> Interleave<T>(
    this IEnumerable<T> sequenceA,
    IEnumerable<T> sequenceB,
    )
    {
    var enumA = sequenceA.GetEnumerator();
    var enumB = sequenceB.GetEnumerator();

    // As long as there are elements in sequence A
    while (enumA.MoveNext())
    {
    // Take an element from sequence A
    yield return enumA.Current;

    // And, if possible,
    if (enumB.MoveNext())
    {
    // Take an element from sequence B
    yield return enumB.Current;
    }
    }

    // If there are any elements left over in sequence B
    while (enumB.MoveNext())
    {
    // Take each of them
    yield return enumB.Current;
    }
    }


    As for the question of time/resource demands: Is the invocation of an extension method, and handling of the enumerators more efficient then manual list creation and management? I would guess so, but I don't know, and I don't particularly care. I would be very confident in guessing that whatever performance gains you make by using one technique over the other will be dwarfed by, for example, the I/O operations your program is making. If (and only if) you notice performance degradation in your application, you should revisit the question with the help of a profiler.



    Here is a demonstration comparing the behavior of your original implementation to the enumerator-based technique. They are almost the same but you may want to make some tweaks. It might be a good idea to adapt that demonstration into your unit test suite. Edit: As t3chb0t points out, it is also important to ensure your enumerators are Disposed, which this demo code fails to do.






    share|improve this answer























    • this is a nice idea with Interleave and it would be even better if it took a single collection and a comparer to create the two other collections internally.
      – t3chb0t
      Nov 8 at 19:46










    • One complication that could arise (if we accept a key selector like child => child.Sex and not just a boolean filter) is the possibility of having N groups. That would be an interesting challenge to solve, but I would start to worry about over-engineering.
      – benj2240
      Nov 8 at 20:00










    • Challange accepted! I like over-engineering! (ok, as coding-sport, one can learn a lot - not in production) :-]
      – t3chb0t
      Nov 8 at 20:19










    • ok, this wasn't that difficult... take a look at my edit.
      – t3chb0t
      Nov 8 at 20:56















    up vote
    6
    down vote



    accepted










    It looks like the core of your problem is taking two sequences and "interleaving" them, alternating elements for as long as possible, but allowing for the sequences to be different lengths. Your solution will definitely do that.



    BUT. It would be cleaner if you were able to avoid building up a List element-by-element, and if possible also avoid manual index management. My rule of thumb is "If you never access a list by index, you'll never have index-related bugs."



    One way to do this would be to use enumerators. Your algorithm could look something like this:



    while enumerator A has elements:
    yield an element from enumerator A
    if enumeratorB has another element:
    yield an element from enumerator B

    while enumerator B has elements:
    yield an element from enumerator B


    With this approach, you don't even need to know how many elements there are; you simply "go until you're done".



    If I were writing this code, I would probably write it as an extension method, and call it like this:





    private List<Child> MixGender(List<Child> children)
    {
    return children.Where(c => c.Sex == "male")
    .Interleave(children.Where(c => c.Sex == "female"))
    .ToList();
    }




    /// <summary>
    /// Mix the elements of the two sequences, alternating elements
    /// one by one for as long as possible. If one sequence has more
    /// elements than the other, its leftovers will appear at the
    /// end of the mixed sequence.
    /// </summary>
    public static IEnumerable<T> Interleave<T>(
    this IEnumerable<T> sequenceA,
    IEnumerable<T> sequenceB,
    )
    {
    var enumA = sequenceA.GetEnumerator();
    var enumB = sequenceB.GetEnumerator();

    // As long as there are elements in sequence A
    while (enumA.MoveNext())
    {
    // Take an element from sequence A
    yield return enumA.Current;

    // And, if possible,
    if (enumB.MoveNext())
    {
    // Take an element from sequence B
    yield return enumB.Current;
    }
    }

    // If there are any elements left over in sequence B
    while (enumB.MoveNext())
    {
    // Take each of them
    yield return enumB.Current;
    }
    }


    As for the question of time/resource demands: Is the invocation of an extension method, and handling of the enumerators more efficient then manual list creation and management? I would guess so, but I don't know, and I don't particularly care. I would be very confident in guessing that whatever performance gains you make by using one technique over the other will be dwarfed by, for example, the I/O operations your program is making. If (and only if) you notice performance degradation in your application, you should revisit the question with the help of a profiler.



    Here is a demonstration comparing the behavior of your original implementation to the enumerator-based technique. They are almost the same but you may want to make some tweaks. It might be a good idea to adapt that demonstration into your unit test suite. Edit: As t3chb0t points out, it is also important to ensure your enumerators are Disposed, which this demo code fails to do.






    share|improve this answer























    • this is a nice idea with Interleave and it would be even better if it took a single collection and a comparer to create the two other collections internally.
      – t3chb0t
      Nov 8 at 19:46










    • One complication that could arise (if we accept a key selector like child => child.Sex and not just a boolean filter) is the possibility of having N groups. That would be an interesting challenge to solve, but I would start to worry about over-engineering.
      – benj2240
      Nov 8 at 20:00










    • Challange accepted! I like over-engineering! (ok, as coding-sport, one can learn a lot - not in production) :-]
      – t3chb0t
      Nov 8 at 20:19










    • ok, this wasn't that difficult... take a look at my edit.
      – t3chb0t
      Nov 8 at 20:56













    up vote
    6
    down vote



    accepted







    up vote
    6
    down vote



    accepted






    It looks like the core of your problem is taking two sequences and "interleaving" them, alternating elements for as long as possible, but allowing for the sequences to be different lengths. Your solution will definitely do that.



    BUT. It would be cleaner if you were able to avoid building up a List element-by-element, and if possible also avoid manual index management. My rule of thumb is "If you never access a list by index, you'll never have index-related bugs."



    One way to do this would be to use enumerators. Your algorithm could look something like this:



    while enumerator A has elements:
    yield an element from enumerator A
    if enumeratorB has another element:
    yield an element from enumerator B

    while enumerator B has elements:
    yield an element from enumerator B


    With this approach, you don't even need to know how many elements there are; you simply "go until you're done".



    If I were writing this code, I would probably write it as an extension method, and call it like this:





    private List<Child> MixGender(List<Child> children)
    {
    return children.Where(c => c.Sex == "male")
    .Interleave(children.Where(c => c.Sex == "female"))
    .ToList();
    }




    /// <summary>
    /// Mix the elements of the two sequences, alternating elements
    /// one by one for as long as possible. If one sequence has more
    /// elements than the other, its leftovers will appear at the
    /// end of the mixed sequence.
    /// </summary>
    public static IEnumerable<T> Interleave<T>(
    this IEnumerable<T> sequenceA,
    IEnumerable<T> sequenceB,
    )
    {
    var enumA = sequenceA.GetEnumerator();
    var enumB = sequenceB.GetEnumerator();

    // As long as there are elements in sequence A
    while (enumA.MoveNext())
    {
    // Take an element from sequence A
    yield return enumA.Current;

    // And, if possible,
    if (enumB.MoveNext())
    {
    // Take an element from sequence B
    yield return enumB.Current;
    }
    }

    // If there are any elements left over in sequence B
    while (enumB.MoveNext())
    {
    // Take each of them
    yield return enumB.Current;
    }
    }


    As for the question of time/resource demands: Is the invocation of an extension method, and handling of the enumerators more efficient then manual list creation and management? I would guess so, but I don't know, and I don't particularly care. I would be very confident in guessing that whatever performance gains you make by using one technique over the other will be dwarfed by, for example, the I/O operations your program is making. If (and only if) you notice performance degradation in your application, you should revisit the question with the help of a profiler.



    Here is a demonstration comparing the behavior of your original implementation to the enumerator-based technique. They are almost the same but you may want to make some tweaks. It might be a good idea to adapt that demonstration into your unit test suite. Edit: As t3chb0t points out, it is also important to ensure your enumerators are Disposed, which this demo code fails to do.






    share|improve this answer














    It looks like the core of your problem is taking two sequences and "interleaving" them, alternating elements for as long as possible, but allowing for the sequences to be different lengths. Your solution will definitely do that.



    BUT. It would be cleaner if you were able to avoid building up a List element-by-element, and if possible also avoid manual index management. My rule of thumb is "If you never access a list by index, you'll never have index-related bugs."



    One way to do this would be to use enumerators. Your algorithm could look something like this:



    while enumerator A has elements:
    yield an element from enumerator A
    if enumeratorB has another element:
    yield an element from enumerator B

    while enumerator B has elements:
    yield an element from enumerator B


    With this approach, you don't even need to know how many elements there are; you simply "go until you're done".



    If I were writing this code, I would probably write it as an extension method, and call it like this:





    private List<Child> MixGender(List<Child> children)
    {
    return children.Where(c => c.Sex == "male")
    .Interleave(children.Where(c => c.Sex == "female"))
    .ToList();
    }




    /// <summary>
    /// Mix the elements of the two sequences, alternating elements
    /// one by one for as long as possible. If one sequence has more
    /// elements than the other, its leftovers will appear at the
    /// end of the mixed sequence.
    /// </summary>
    public static IEnumerable<T> Interleave<T>(
    this IEnumerable<T> sequenceA,
    IEnumerable<T> sequenceB,
    )
    {
    var enumA = sequenceA.GetEnumerator();
    var enumB = sequenceB.GetEnumerator();

    // As long as there are elements in sequence A
    while (enumA.MoveNext())
    {
    // Take an element from sequence A
    yield return enumA.Current;

    // And, if possible,
    if (enumB.MoveNext())
    {
    // Take an element from sequence B
    yield return enumB.Current;
    }
    }

    // If there are any elements left over in sequence B
    while (enumB.MoveNext())
    {
    // Take each of them
    yield return enumB.Current;
    }
    }


    As for the question of time/resource demands: Is the invocation of an extension method, and handling of the enumerators more efficient then manual list creation and management? I would guess so, but I don't know, and I don't particularly care. I would be very confident in guessing that whatever performance gains you make by using one technique over the other will be dwarfed by, for example, the I/O operations your program is making. If (and only if) you notice performance degradation in your application, you should revisit the question with the help of a profiler.



    Here is a demonstration comparing the behavior of your original implementation to the enumerator-based technique. They are almost the same but you may want to make some tweaks. It might be a good idea to adapt that demonstration into your unit test suite. Edit: As t3chb0t points out, it is also important to ensure your enumerators are Disposed, which this demo code fails to do.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 8 at 21:10

























    answered Nov 8 at 19:08









    benj2240

    4467




    4467












    • this is a nice idea with Interleave and it would be even better if it took a single collection and a comparer to create the two other collections internally.
      – t3chb0t
      Nov 8 at 19:46










    • One complication that could arise (if we accept a key selector like child => child.Sex and not just a boolean filter) is the possibility of having N groups. That would be an interesting challenge to solve, but I would start to worry about over-engineering.
      – benj2240
      Nov 8 at 20:00










    • Challange accepted! I like over-engineering! (ok, as coding-sport, one can learn a lot - not in production) :-]
      – t3chb0t
      Nov 8 at 20:19










    • ok, this wasn't that difficult... take a look at my edit.
      – t3chb0t
      Nov 8 at 20:56


















    • this is a nice idea with Interleave and it would be even better if it took a single collection and a comparer to create the two other collections internally.
      – t3chb0t
      Nov 8 at 19:46










    • One complication that could arise (if we accept a key selector like child => child.Sex and not just a boolean filter) is the possibility of having N groups. That would be an interesting challenge to solve, but I would start to worry about over-engineering.
      – benj2240
      Nov 8 at 20:00










    • Challange accepted! I like over-engineering! (ok, as coding-sport, one can learn a lot - not in production) :-]
      – t3chb0t
      Nov 8 at 20:19










    • ok, this wasn't that difficult... take a look at my edit.
      – t3chb0t
      Nov 8 at 20:56
















    this is a nice idea with Interleave and it would be even better if it took a single collection and a comparer to create the two other collections internally.
    – t3chb0t
    Nov 8 at 19:46




    this is a nice idea with Interleave and it would be even better if it took a single collection and a comparer to create the two other collections internally.
    – t3chb0t
    Nov 8 at 19:46












    One complication that could arise (if we accept a key selector like child => child.Sex and not just a boolean filter) is the possibility of having N groups. That would be an interesting challenge to solve, but I would start to worry about over-engineering.
    – benj2240
    Nov 8 at 20:00




    One complication that could arise (if we accept a key selector like child => child.Sex and not just a boolean filter) is the possibility of having N groups. That would be an interesting challenge to solve, but I would start to worry about over-engineering.
    – benj2240
    Nov 8 at 20:00












    Challange accepted! I like over-engineering! (ok, as coding-sport, one can learn a lot - not in production) :-]
    – t3chb0t
    Nov 8 at 20:19




    Challange accepted! I like over-engineering! (ok, as coding-sport, one can learn a lot - not in production) :-]
    – t3chb0t
    Nov 8 at 20:19












    ok, this wasn't that difficult... take a look at my edit.
    – t3chb0t
    Nov 8 at 20:56




    ok, this wasn't that difficult... take a look at my edit.
    – t3chb0t
    Nov 8 at 20:56












    up vote
    9
    down vote













    Not a fan of LINQ, yet? Then look here... You could start by grouping Child by Sex into a new lookup, this would replace the two Wheres. In the next step you Zip them together and take one item from each collection at a time. You create from then new tiny collections that you finally flatten with SelectMany. No calculation necessary.



    var groups = items.ToLookup(i => i.Sex);
    var alternating =
    groups["male"]
    .Zip(groups["female"], (x, y) => new { x, y })
    .SelectMany(t => t)
    .ToList();


    This will however require that both collections have the same length because Zip will go only as far as the shorter collection.





    Some nice improvement to you method would be to make it work for any group of items. When you pass it a custom comparer you can GroupBy the items and iterate over each group until there is nothing left to yield. Since enumerators are disposable you need to make sure to dispose them properly at the end thus the finally block.



    public static IEnumerable<T> Interleave<T>(this IEnumerable<T> source, IEqualityComparer<T> comparer)
    {
    var groups = source.GroupBy(x => x, comparer);
    var enumerators = groups.Select(g => g.GetEnumerator()).ToList();
    try
    {
    var any = false;
    do
    {
    any = false;
    foreach (var e in enumerators)
    {
    if (e.MoveNext())
    {
    any = true;
    yield return e.Current;
    }
    }
    } while (any);
    }
    finally
    {
    foreach (var e in enumerators)
    {
    e.Dispose();
    }
    }
    }


    An example usage could then look like this:



    var innerComparer = StringComparer.OrdinalIgnoreCase;
    var comparer = EqualityComparerFactory<Child>.Create
    (
    (x, y) => innerComparer.Equals(x.Sex, y.Sex),
    obj => innerComparer.GetHashCode(obj.Sex)
    );
    var result = items.Interleave(comparer);





    share|improve this answer



















    • 1




      instead of passing in an IEqualityComparer<T> how about a Func<T, TKey> and grouping off of that? Then you don't need EqualityComparerFactory and can still interleave over all the different values of a property.
      – C.M.
      Nov 8 at 21:52










    • @C.M. I think it would be a good idea to have both APIs because many linq extensions allow you to do it in the one or the other way with the comparer if you need something customized.
      – t3chb0t
      Nov 9 at 9:22















    up vote
    9
    down vote













    Not a fan of LINQ, yet? Then look here... You could start by grouping Child by Sex into a new lookup, this would replace the two Wheres. In the next step you Zip them together and take one item from each collection at a time. You create from then new tiny collections that you finally flatten with SelectMany. No calculation necessary.



    var groups = items.ToLookup(i => i.Sex);
    var alternating =
    groups["male"]
    .Zip(groups["female"], (x, y) => new { x, y })
    .SelectMany(t => t)
    .ToList();


    This will however require that both collections have the same length because Zip will go only as far as the shorter collection.





    Some nice improvement to you method would be to make it work for any group of items. When you pass it a custom comparer you can GroupBy the items and iterate over each group until there is nothing left to yield. Since enumerators are disposable you need to make sure to dispose them properly at the end thus the finally block.



    public static IEnumerable<T> Interleave<T>(this IEnumerable<T> source, IEqualityComparer<T> comparer)
    {
    var groups = source.GroupBy(x => x, comparer);
    var enumerators = groups.Select(g => g.GetEnumerator()).ToList();
    try
    {
    var any = false;
    do
    {
    any = false;
    foreach (var e in enumerators)
    {
    if (e.MoveNext())
    {
    any = true;
    yield return e.Current;
    }
    }
    } while (any);
    }
    finally
    {
    foreach (var e in enumerators)
    {
    e.Dispose();
    }
    }
    }


    An example usage could then look like this:



    var innerComparer = StringComparer.OrdinalIgnoreCase;
    var comparer = EqualityComparerFactory<Child>.Create
    (
    (x, y) => innerComparer.Equals(x.Sex, y.Sex),
    obj => innerComparer.GetHashCode(obj.Sex)
    );
    var result = items.Interleave(comparer);





    share|improve this answer



















    • 1




      instead of passing in an IEqualityComparer<T> how about a Func<T, TKey> and grouping off of that? Then you don't need EqualityComparerFactory and can still interleave over all the different values of a property.
      – C.M.
      Nov 8 at 21:52










    • @C.M. I think it would be a good idea to have both APIs because many linq extensions allow you to do it in the one or the other way with the comparer if you need something customized.
      – t3chb0t
      Nov 9 at 9:22













    up vote
    9
    down vote










    up vote
    9
    down vote









    Not a fan of LINQ, yet? Then look here... You could start by grouping Child by Sex into a new lookup, this would replace the two Wheres. In the next step you Zip them together and take one item from each collection at a time. You create from then new tiny collections that you finally flatten with SelectMany. No calculation necessary.



    var groups = items.ToLookup(i => i.Sex);
    var alternating =
    groups["male"]
    .Zip(groups["female"], (x, y) => new { x, y })
    .SelectMany(t => t)
    .ToList();


    This will however require that both collections have the same length because Zip will go only as far as the shorter collection.





    Some nice improvement to you method would be to make it work for any group of items. When you pass it a custom comparer you can GroupBy the items and iterate over each group until there is nothing left to yield. Since enumerators are disposable you need to make sure to dispose them properly at the end thus the finally block.



    public static IEnumerable<T> Interleave<T>(this IEnumerable<T> source, IEqualityComparer<T> comparer)
    {
    var groups = source.GroupBy(x => x, comparer);
    var enumerators = groups.Select(g => g.GetEnumerator()).ToList();
    try
    {
    var any = false;
    do
    {
    any = false;
    foreach (var e in enumerators)
    {
    if (e.MoveNext())
    {
    any = true;
    yield return e.Current;
    }
    }
    } while (any);
    }
    finally
    {
    foreach (var e in enumerators)
    {
    e.Dispose();
    }
    }
    }


    An example usage could then look like this:



    var innerComparer = StringComparer.OrdinalIgnoreCase;
    var comparer = EqualityComparerFactory<Child>.Create
    (
    (x, y) => innerComparer.Equals(x.Sex, y.Sex),
    obj => innerComparer.GetHashCode(obj.Sex)
    );
    var result = items.Interleave(comparer);





    share|improve this answer














    Not a fan of LINQ, yet? Then look here... You could start by grouping Child by Sex into a new lookup, this would replace the two Wheres. In the next step you Zip them together and take one item from each collection at a time. You create from then new tiny collections that you finally flatten with SelectMany. No calculation necessary.



    var groups = items.ToLookup(i => i.Sex);
    var alternating =
    groups["male"]
    .Zip(groups["female"], (x, y) => new { x, y })
    .SelectMany(t => t)
    .ToList();


    This will however require that both collections have the same length because Zip will go only as far as the shorter collection.





    Some nice improvement to you method would be to make it work for any group of items. When you pass it a custom comparer you can GroupBy the items and iterate over each group until there is nothing left to yield. Since enumerators are disposable you need to make sure to dispose them properly at the end thus the finally block.



    public static IEnumerable<T> Interleave<T>(this IEnumerable<T> source, IEqualityComparer<T> comparer)
    {
    var groups = source.GroupBy(x => x, comparer);
    var enumerators = groups.Select(g => g.GetEnumerator()).ToList();
    try
    {
    var any = false;
    do
    {
    any = false;
    foreach (var e in enumerators)
    {
    if (e.MoveNext())
    {
    any = true;
    yield return e.Current;
    }
    }
    } while (any);
    }
    finally
    {
    foreach (var e in enumerators)
    {
    e.Dispose();
    }
    }
    }


    An example usage could then look like this:



    var innerComparer = StringComparer.OrdinalIgnoreCase;
    var comparer = EqualityComparerFactory<Child>.Create
    (
    (x, y) => innerComparer.Equals(x.Sex, y.Sex),
    obj => innerComparer.GetHashCode(obj.Sex)
    );
    var result = items.Interleave(comparer);






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 8 at 20:54

























    answered Nov 8 at 18:02









    t3chb0t

    33.6k744108




    33.6k744108








    • 1




      instead of passing in an IEqualityComparer<T> how about a Func<T, TKey> and grouping off of that? Then you don't need EqualityComparerFactory and can still interleave over all the different values of a property.
      – C.M.
      Nov 8 at 21:52










    • @C.M. I think it would be a good idea to have both APIs because many linq extensions allow you to do it in the one or the other way with the comparer if you need something customized.
      – t3chb0t
      Nov 9 at 9:22














    • 1




      instead of passing in an IEqualityComparer<T> how about a Func<T, TKey> and grouping off of that? Then you don't need EqualityComparerFactory and can still interleave over all the different values of a property.
      – C.M.
      Nov 8 at 21:52










    • @C.M. I think it would be a good idea to have both APIs because many linq extensions allow you to do it in the one or the other way with the comparer if you need something customized.
      – t3chb0t
      Nov 9 at 9:22








    1




    1




    instead of passing in an IEqualityComparer<T> how about a Func<T, TKey> and grouping off of that? Then you don't need EqualityComparerFactory and can still interleave over all the different values of a property.
    – C.M.
    Nov 8 at 21:52




    instead of passing in an IEqualityComparer<T> how about a Func<T, TKey> and grouping off of that? Then you don't need EqualityComparerFactory and can still interleave over all the different values of a property.
    – C.M.
    Nov 8 at 21:52












    @C.M. I think it would be a good idea to have both APIs because many linq extensions allow you to do it in the one or the other way with the comparer if you need something customized.
    – t3chb0t
    Nov 9 at 9:22




    @C.M. I think it would be a good idea to have both APIs because many linq extensions allow you to do it in the one or the other way with the comparer if you need something customized.
    – t3chb0t
    Nov 9 at 9:22










    up vote
    8
    down vote













    My only comment is don't mutate the input and then return it.



    private List<Child> MixGender(List<Child> children)


    Return a fresh List<Child>.



    Male and female should be enum.






    share|improve this answer























    • I was just about to mention it ;-]
      – t3chb0t
      Nov 8 at 17:57










    • ok, now even I wonder why the downvote? This is an important point presented here.
      – t3chb0t
      Nov 8 at 18:05










    • I don't typically sweat the down votes. I have had way better answers than this get multiple down votes. If I am confused I will ask why but not to argue the down vote.
      – paparazzo
      Nov 8 at 19:52








    • 1




      I think mutating a list is acceptable, but agree it's cleaner to return a fresh list. It would depend on how big the list is and if using a lot of memory was a concern. (I find 99% of lists I deal with are less than 10 items.) -- I would add that if you are going to mutate the list then don't return the list, make the method void (or C# equivalent) to make it clear it's mutating.
      – Captain Man
      Nov 9 at 14:50












    • yes I noticed it too. How it is possible and why int is not mutating for example? I am not able to google something about "mutate c#"
      – Tomas Kanok
      Nov 9 at 15:52















    up vote
    8
    down vote













    My only comment is don't mutate the input and then return it.



    private List<Child> MixGender(List<Child> children)


    Return a fresh List<Child>.



    Male and female should be enum.






    share|improve this answer























    • I was just about to mention it ;-]
      – t3chb0t
      Nov 8 at 17:57










    • ok, now even I wonder why the downvote? This is an important point presented here.
      – t3chb0t
      Nov 8 at 18:05










    • I don't typically sweat the down votes. I have had way better answers than this get multiple down votes. If I am confused I will ask why but not to argue the down vote.
      – paparazzo
      Nov 8 at 19:52








    • 1




      I think mutating a list is acceptable, but agree it's cleaner to return a fresh list. It would depend on how big the list is and if using a lot of memory was a concern. (I find 99% of lists I deal with are less than 10 items.) -- I would add that if you are going to mutate the list then don't return the list, make the method void (or C# equivalent) to make it clear it's mutating.
      – Captain Man
      Nov 9 at 14:50












    • yes I noticed it too. How it is possible and why int is not mutating for example? I am not able to google something about "mutate c#"
      – Tomas Kanok
      Nov 9 at 15:52













    up vote
    8
    down vote










    up vote
    8
    down vote









    My only comment is don't mutate the input and then return it.



    private List<Child> MixGender(List<Child> children)


    Return a fresh List<Child>.



    Male and female should be enum.






    share|improve this answer














    My only comment is don't mutate the input and then return it.



    private List<Child> MixGender(List<Child> children)


    Return a fresh List<Child>.



    Male and female should be enum.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 8 at 19:48

























    answered Nov 8 at 17:54









    paparazzo

    4,9911733




    4,9911733












    • I was just about to mention it ;-]
      – t3chb0t
      Nov 8 at 17:57










    • ok, now even I wonder why the downvote? This is an important point presented here.
      – t3chb0t
      Nov 8 at 18:05










    • I don't typically sweat the down votes. I have had way better answers than this get multiple down votes. If I am confused I will ask why but not to argue the down vote.
      – paparazzo
      Nov 8 at 19:52








    • 1




      I think mutating a list is acceptable, but agree it's cleaner to return a fresh list. It would depend on how big the list is and if using a lot of memory was a concern. (I find 99% of lists I deal with are less than 10 items.) -- I would add that if you are going to mutate the list then don't return the list, make the method void (or C# equivalent) to make it clear it's mutating.
      – Captain Man
      Nov 9 at 14:50












    • yes I noticed it too. How it is possible and why int is not mutating for example? I am not able to google something about "mutate c#"
      – Tomas Kanok
      Nov 9 at 15:52


















    • I was just about to mention it ;-]
      – t3chb0t
      Nov 8 at 17:57










    • ok, now even I wonder why the downvote? This is an important point presented here.
      – t3chb0t
      Nov 8 at 18:05










    • I don't typically sweat the down votes. I have had way better answers than this get multiple down votes. If I am confused I will ask why but not to argue the down vote.
      – paparazzo
      Nov 8 at 19:52








    • 1




      I think mutating a list is acceptable, but agree it's cleaner to return a fresh list. It would depend on how big the list is and if using a lot of memory was a concern. (I find 99% of lists I deal with are less than 10 items.) -- I would add that if you are going to mutate the list then don't return the list, make the method void (or C# equivalent) to make it clear it's mutating.
      – Captain Man
      Nov 9 at 14:50












    • yes I noticed it too. How it is possible and why int is not mutating for example? I am not able to google something about "mutate c#"
      – Tomas Kanok
      Nov 9 at 15:52
















    I was just about to mention it ;-]
    – t3chb0t
    Nov 8 at 17:57




    I was just about to mention it ;-]
    – t3chb0t
    Nov 8 at 17:57












    ok, now even I wonder why the downvote? This is an important point presented here.
    – t3chb0t
    Nov 8 at 18:05




    ok, now even I wonder why the downvote? This is an important point presented here.
    – t3chb0t
    Nov 8 at 18:05












    I don't typically sweat the down votes. I have had way better answers than this get multiple down votes. If I am confused I will ask why but not to argue the down vote.
    – paparazzo
    Nov 8 at 19:52






    I don't typically sweat the down votes. I have had way better answers than this get multiple down votes. If I am confused I will ask why but not to argue the down vote.
    – paparazzo
    Nov 8 at 19:52






    1




    1




    I think mutating a list is acceptable, but agree it's cleaner to return a fresh list. It would depend on how big the list is and if using a lot of memory was a concern. (I find 99% of lists I deal with are less than 10 items.) -- I would add that if you are going to mutate the list then don't return the list, make the method void (or C# equivalent) to make it clear it's mutating.
    – Captain Man
    Nov 9 at 14:50






    I think mutating a list is acceptable, but agree it's cleaner to return a fresh list. It would depend on how big the list is and if using a lot of memory was a concern. (I find 99% of lists I deal with are less than 10 items.) -- I would add that if you are going to mutate the list then don't return the list, make the method void (or C# equivalent) to make it clear it's mutating.
    – Captain Man
    Nov 9 at 14:50














    yes I noticed it too. How it is possible and why int is not mutating for example? I am not able to google something about "mutate c#"
    – Tomas Kanok
    Nov 9 at 15:52




    yes I noticed it too. How it is possible and why int is not mutating for example? I am not able to google something about "mutate c#"
    – Tomas Kanok
    Nov 9 at 15:52










    up vote
    4
    down vote













    You can avoid building up an inner list in the method using yield returnin the following way:



    private IEnumerable<Child> MixGender(List<Child> children)
    {
    List<Child> male = children.Where(c => c.Sex == "male").ToList();
    List<Child> female = children.Where(c => c.Sex == "female").ToList();

    int childrenCount = children.Count;
    int indexMale = 0;
    int indexFemale = 0;

    for (int i = 0; i < childrenCount; i++)
    {
    if (i % 2 == 1)
    {
    if (indexMale < male.Count)
    {
    yield return male[indexMale];
    indexMale++;
    }
    else
    {
    yield return female[indexFemale];
    indexFemale++;
    }
    }
    else
    {
    if (indexFemale < female.Count)
    {
    yield return female[indexFemale];
    indexFemale++;
    }
    else
    {
    yield return male[indexMale];
    indexMale++;
    }
    }
    }
    }





    share|improve this answer

























      up vote
      4
      down vote













      You can avoid building up an inner list in the method using yield returnin the following way:



      private IEnumerable<Child> MixGender(List<Child> children)
      {
      List<Child> male = children.Where(c => c.Sex == "male").ToList();
      List<Child> female = children.Where(c => c.Sex == "female").ToList();

      int childrenCount = children.Count;
      int indexMale = 0;
      int indexFemale = 0;

      for (int i = 0; i < childrenCount; i++)
      {
      if (i % 2 == 1)
      {
      if (indexMale < male.Count)
      {
      yield return male[indexMale];
      indexMale++;
      }
      else
      {
      yield return female[indexFemale];
      indexFemale++;
      }
      }
      else
      {
      if (indexFemale < female.Count)
      {
      yield return female[indexFemale];
      indexFemale++;
      }
      else
      {
      yield return male[indexMale];
      indexMale++;
      }
      }
      }
      }





      share|improve this answer























        up vote
        4
        down vote










        up vote
        4
        down vote









        You can avoid building up an inner list in the method using yield returnin the following way:



        private IEnumerable<Child> MixGender(List<Child> children)
        {
        List<Child> male = children.Where(c => c.Sex == "male").ToList();
        List<Child> female = children.Where(c => c.Sex == "female").ToList();

        int childrenCount = children.Count;
        int indexMale = 0;
        int indexFemale = 0;

        for (int i = 0; i < childrenCount; i++)
        {
        if (i % 2 == 1)
        {
        if (indexMale < male.Count)
        {
        yield return male[indexMale];
        indexMale++;
        }
        else
        {
        yield return female[indexFemale];
        indexFemale++;
        }
        }
        else
        {
        if (indexFemale < female.Count)
        {
        yield return female[indexFemale];
        indexFemale++;
        }
        else
        {
        yield return male[indexMale];
        indexMale++;
        }
        }
        }
        }





        share|improve this answer












        You can avoid building up an inner list in the method using yield returnin the following way:



        private IEnumerable<Child> MixGender(List<Child> children)
        {
        List<Child> male = children.Where(c => c.Sex == "male").ToList();
        List<Child> female = children.Where(c => c.Sex == "female").ToList();

        int childrenCount = children.Count;
        int indexMale = 0;
        int indexFemale = 0;

        for (int i = 0; i < childrenCount; i++)
        {
        if (i % 2 == 1)
        {
        if (indexMale < male.Count)
        {
        yield return male[indexMale];
        indexMale++;
        }
        else
        {
        yield return female[indexFemale];
        indexFemale++;
        }
        }
        else
        {
        if (indexFemale < female.Count)
        {
        yield return female[indexFemale];
        indexFemale++;
        }
        else
        {
        yield return male[indexMale];
        indexMale++;
        }
        }
        }
        }






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 8 at 20:16









        Henrik Hansen

        6,1531722




        6,1531722






























             

            draft saved


            draft discarded



















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207240%2falternating-items-in-a-collection%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Schultheiß

            Verwaltungsgliederung Dänemarks

            Liste der Kulturdenkmale in Wilsdruff