Alternating items in a collection

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
1
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









New contributor




Tomas Kanok is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.















  • 3




    Could you reframe your question and the requirements? You write about mixing items in lists but then about sorting... I'm very confused.
    – t3chb0t
    3 hours ago










  • 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
    1 hour ago










  • I follow. It looks OK to me.
    – paparazzo
    1 hour ago










  • ok, now it makes sense, thank you for clarifying this ;-)
    – t3chb0t
    1 hour ago














up vote
1
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









New contributor




Tomas Kanok is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.















  • 3




    Could you reframe your question and the requirements? You write about mixing items in lists but then about sorting... I'm very confused.
    – t3chb0t
    3 hours ago










  • 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
    1 hour ago










  • I follow. It looks OK to me.
    – paparazzo
    1 hour ago










  • ok, now it makes sense, thank you for clarifying this ;-)
    – t3chb0t
    1 hour ago












up vote
1
down vote

favorite









up vote
1
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









New contributor




Tomas Kanok is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











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









New contributor




Tomas Kanok is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




Tomas Kanok is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 1 hour ago









t3chb0t

33.1k744106




33.1k744106






New contributor




Tomas Kanok is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 3 hours ago









Tomas Kanok

61




61




New contributor




Tomas Kanok is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





Tomas Kanok is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






Tomas Kanok is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







  • 3




    Could you reframe your question and the requirements? You write about mixing items in lists but then about sorting... I'm very confused.
    – t3chb0t
    3 hours ago










  • 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
    1 hour ago










  • I follow. It looks OK to me.
    – paparazzo
    1 hour ago










  • ok, now it makes sense, thank you for clarifying this ;-)
    – t3chb0t
    1 hour ago












  • 3




    Could you reframe your question and the requirements? You write about mixing items in lists but then about sorting... I'm very confused.
    – t3chb0t
    3 hours ago










  • 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
    1 hour ago










  • I follow. It looks OK to me.
    – paparazzo
    1 hour ago










  • ok, now it makes sense, thank you for clarifying this ;-)
    – t3chb0t
    1 hour ago







3




3




Could you reframe your question and the requirements? You write about mixing items in lists but then about sorting... I'm very confused.
– t3chb0t
3 hours ago




Could you reframe your question and the requirements? You write about mixing items in lists but then about sorting... I'm very confused.
– t3chb0t
3 hours ago












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
1 hour ago




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
1 hour ago












I follow. It looks OK to me.
– paparazzo
1 hour ago




I follow. It looks OK to me.
– paparazzo
1 hour ago












ok, now it makes sense, thank you for clarifying this ;-)
– t3chb0t
1 hour ago




ok, now it makes sense, thank you for clarifying this ;-)
– t3chb0t
1 hour ago










3 Answers
3






active

oldest

votes

















up vote
2
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>.






share|improve this answer




















  • I was just about to mention it ;-]
    – t3chb0t
    1 hour ago










  • ok, now even I wonder why the downvote? This is an important point presented here.
    – t3chb0t
    1 hour ago

















up vote
2
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.






share|improve this answer



























    up vote
    1
    down vote













    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.






    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
      );



      );






      Tomas Kanok is a new contributor. Be nice, and check out our Code of Conduct.









       

      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






























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      2
      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>.






      share|improve this answer




















      • I was just about to mention it ;-]
        – t3chb0t
        1 hour ago










      • ok, now even I wonder why the downvote? This is an important point presented here.
        – t3chb0t
        1 hour ago














      up vote
      2
      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>.






      share|improve this answer




















      • I was just about to mention it ;-]
        – t3chb0t
        1 hour ago










      • ok, now even I wonder why the downvote? This is an important point presented here.
        – t3chb0t
        1 hour ago












      up vote
      2
      down vote










      up vote
      2
      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>.






      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>.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered 1 hour ago









      paparazzo

      4,9381733




      4,9381733











      • I was just about to mention it ;-]
        – t3chb0t
        1 hour ago










      • ok, now even I wonder why the downvote? This is an important point presented here.
        – t3chb0t
        1 hour ago
















      • I was just about to mention it ;-]
        – t3chb0t
        1 hour ago










      • ok, now even I wonder why the downvote? This is an important point presented here.
        – t3chb0t
        1 hour ago















      I was just about to mention it ;-]
      – t3chb0t
      1 hour ago




      I was just about to mention it ;-]
      – t3chb0t
      1 hour ago












      ok, now even I wonder why the downvote? This is an important point presented here.
      – t3chb0t
      1 hour ago




      ok, now even I wonder why the downvote? This is an important point presented here.
      – t3chb0t
      1 hour ago












      up vote
      2
      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.






      share|improve this answer
























        up vote
        2
        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.






        share|improve this answer






















          up vote
          2
          down vote










          up vote
          2
          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.






          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.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered 1 hour ago









          t3chb0t

          33.1k744106




          33.1k744106




















              up vote
              1
              down vote













              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.






              share|improve this answer
























                up vote
                1
                down vote













                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.






                share|improve this answer






















                  up vote
                  1
                  down vote










                  up vote
                  1
                  down vote









                  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.






                  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.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered 17 mins ago









                  benj2240

                  3463




                  3463




















                      Tomas Kanok is a new contributor. Be nice, and check out our Code of Conduct.









                       

                      draft saved


                      draft discarded


















                      Tomas Kanok is a new contributor. Be nice, and check out our Code of Conduct.












                      Tomas Kanok is a new contributor. Be nice, and check out our Code of Conduct.











                      Tomas Kanok is a new contributor. Be nice, and check out our Code of Conduct.













                       


                      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













































































                      Comments

                      Popular posts from this blog

                      What does second last employer means? [closed]

                      Installing NextGIS Connect into QGIS 3?

                      One-line joke