Search code examples
c#linq

Return IEnumerable with Linq based on choice


I am trying to figure out a way to solve this issue with Linq, does someone have any idea on how to do this? Trying to find this particular use case has proven to be quite challenging so I hope this question hasn't been asked before even though I suspect I just couldn't find it.

public class Test
{
    public int a;
    public int b;
}

public Test[] testArray;

public enum Choice { A,B, Both = A|B }

public IEnumerable<int> GetEnumerable(Choice choice)
{
    //need to use Linq methods to return an enumerable based on choice
}

//e.g  testArray = { (1,2) (3,4) (5,6)
//calling GetEnumerable(Choice.A)
// 1,3,5
//calling GetEnumerable(Choice.Both)
// 1,2,3,4,5,6

Everyone focused on the wrong aspects of my question, yes the [Flags] attribute is missing, yes the enum items should be a power of 2 to be used as Flags. I already marked the correct answer which is to loop over the collection which is what I did before, I just didn't realize I could yield return a IEnumerable so Implemented an enumerator

All the other solutions use Linq but rely too much on instantiating new objects, for a lazy quick approach that is fine but that's not what I wanted.


Solution

  • If you insist on single Linq query, you can try SelectMany where you can return a required collection to be flatten e.g.

    public IEnumerable<int> GetEnumerable(Choice choice) => testArray
         .SelectMany(item => choice == Choice.Both ? new int[] {item.A, item.B} :
                             choice == Choice.A ? new int[] {item.A} :
                             choice == Choice.B ? new int[] {item.B} :
                                                  new int[] {});
    

    However, I'd rather implement a simple foreach loop without any Linq:

    // Since you use bit combinations, let's do it explicit with [Flags] attribute
    [Flags]
    public enum Choice { 
      None = 0, // let have "None" explicit
      A    = 1,
      B    = 2, 
      Both = A|B 
    }
    
    public IEnumerable<int> GetEnumerable(Choice choice) {
      foreach (var item in testArray) {
        if (choice.HasFlag(Choice.A))
          yield return item.A;
    
        if (choice.HasFlag(Choice.B))
          yield return item.B;
      }
    }