根据选择使用Linq返回IEnumerable

64jmpszr  于 2022-12-06  发布在  其他
关注(0)|答案(3)|浏览(121)

我正在尝试找出一种方法来解决Linq的这个问题,有人知道如何做到这一点吗?试图找到这个特定的用例已经证明是相当具有挑战性的,所以我希望这个问题以前没有被问过,即使我怀疑我只是找不到它。

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

每个人都把注意力集中在我的问题的错误方面,是的,[Flags]属性丢失了,是的,枚举项应该是2的幂才能用作标志。我已经标记了正确的答案,即循环遍历集合,这是我之前所做的,我只是没有意识到我可以生成返回IEnumerable,所以实现了一个枚举器
所有其他的解决方案都使用Linq,但是太依赖于示例化新对象,对于一个懒惰的快速方法来说,这是好的,但这不是我想要的。

kkih6yb8

kkih6yb81#

不需要Linq,我可能会使用switch表达式(尽管这里有一点Linq):

public IEnumerable<int> GetEnumerable(Choice choice)
    => choice switch
    {
        Choice.A => testArray.Select(a => a.Item1),
        Choice.B => testArray.Select(a => a.Item2),
        Choice.Both => testArray.SelectMany(a => new[] { a.Item1, a.Item2 }),
        _ => throw new ArgumentException("Invalid choice")
    };
8yparm6h

8yparm6h2#

枚举A存在继承问题|B == B,所以我把Both改为它自己的case,这样就用一个linq查询解决了这个问题:

public enum Choice { A, B, Both}
public class Test
{
    public int A;
    public int B;

    public Test(int a, int b)
    {
        A = a;
        B = b;
    }
}

public class Program
{
    public static void Main()
    {
        var tests = new List<Test>()
        {
            new Test(1, 2),
            new Test(3, 4),
            new Test(5, 6)
        };

        Console.WriteLine(string.Join(", ", GetEnumerable(tests, Choice.A)));
        Console.WriteLine(string.Join(", ", GetEnumerable(tests, Choice.B)));
        Console.WriteLine(string.Join(", ", GetEnumerable(tests, Choice.Both)));

        /*
         * Console Output:
         *     1, 3, 5
         *     2, 4, 6
         *     1, 2, 3, 4, 5, 6
         */

    }

    private static IEnumerable<int> GetEnumerable(IEnumerable<Test> data, Choice choice)
        => data.SelectMany(d => choice switch
        {
            Choice.A => new List<int> { d.A },
            Choice.B => new List<int> { d.B },
            Choice.Both => new List<int> { d.A, d.B },
            _ => throw new ArgumentException($"No case exists for Choice enum {choice}")
        });

}
tmb3ates

tmb3ates3#

如果你坚持使用单个Linq查询,你可以尝试SelectMany,在那里你可以返回一个需要的 * 集合 * 来进行扁平化,例如。

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[] {});

但是,我宁愿实现一个简单的foreach循环 ,而不使用任何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;
  }
}

相关问题