使用LINQ将一堆布尔值转换为枚举列表

时间:2013-09-10 02:32:58

标签: c# .net linq

说我有这样的课程:

class From
{
    public bool FlagOne { get; set; }
    public bool FlagTwo { get; set; }
    public bool FlagThree { get; set; }
}

...我希望将这些列表转换为以下列表:

class To
{
    public List<Flag> Flags { get; set; }
}

... Flag看起来像这样:

public enum Flag
{
    One,Two,Three
}

我写了一些代码:

var froms = new List<From>
{
    new From {
        FlagOne = false,
        FlagTwo = true,
        FlagThree = true
    },
    new From {
        FlagOne = true,
        FlagTwo = false,
        FlagThree = true
    }
};

var tos = froms.Select(from => new To {
    Flags = // ....... what?  what goes here?
}).ToList();

枚举值的名称和布尔标志无关紧要。应该没有必要的反思。

上下文

我有一个这样的数据库表:

+---------+---------+-----------+
| FlagOne | FlagTwo | FlagThree | 
+=========+=========+===========|
|    0    |    1    |     1     |
+---------+---------+-----------+
|    1    |    0    |     1     |
+---------+---------+-----------+

我希望制作一个如下所示的界面:

+-------------------------------------+
| Lorem blahdiblah FlagTwo, FlagThree |
+-------------------------------------+
| Lorem blahdiblah FlagOne, FlagThree |
+-------------------------------------+

我没有 来做这件事;我只是认为用LINQ解决这是一个有趣的问题,并且无法找到答案。

4 个答案:

答案 0 :(得分:3)

处理此问题的一种方法是在集合中使用可为空的Flag,然后过滤掉null s,如下所示:

var tos = froms
    .Select(f => new To {
        Flags = new[] {
            f.FlagOne   ? (Flag?)Flag.One : null,
            f.FlagTwo   ? (Flag?)Flag.Two : null,
            f.FlagThree ? (Flag?)Flag.Three : null
        }
        .Where(f => f.HasValue)
        .Select(f => f.Value)
        .ToList()
     }).ToList();

Flags赋值中创建的数组有三个Flag?类型的项目 - 每个标志一个。对应于未设置属性的标志变为null s;与set属性对应的标志变为可为空Flag.XYZ

其余的很简单:Where()过滤掉nullSelect()删除可空性,最后ToList()将结果列为一个列表。

答案 1 :(得分:1)

为什么要转换它?

您也可以在枚举中实现标记:

[Flags]
public enum Foo : int {
   Bit1 = 0x01,
   Bit2 = 0x02,
   Bit3 = 0x04
}

然后,您可以通过按位AND操作检查标志是否处于活动状态。例如:

Foo aVariable = Foo.Bit1|Foo.Bit3;//both bit1 and bit3 are enabled

检查bit3是否已启用:

if((aVariable&Foo.Bit3) != 0x00) {
   //flag is enabled, now do something
}
else {
   //flag is disabled, do something else
}

使用这种结构的优点是位表示更紧凑,操作(如按位OR)可以更快地处理,您不必担心位的语义(枚举隐藏实际值比特)。

如果您真的想要枚举可能的值,可以使用通用构造:

public static class Bar {

  public static IEnumerable<T> EnumerateAtoms<T> (this T input) where T : enum {
    foreach(T value in Enum.GetValues(typeof(T))) {
      if((input&val) != 0x00) {
        yield return value;
      }
    }
  }

}

答案 2 :(得分:0)

To ConvertFromFromToTo(From from)
{
    List<Flag> flags = new List<Flag>();

    if (from.FlagOne)   flags.Add(Flag.One);
    if (from.FlagTwo)   flags.Add(Flag.Two);
    if (from.FlagThree) flags.Add(Flag.Three);

    return new To { Flags = flags };
}
var tos = froms.Select(ConvertFromFromToTo).ToList();

答案 3 :(得分:0)

目前还不清楚你打算如何将旗帜bool映射到枚举值,但你可能想要使用这样的东西:

Flags = new List<Flag> { 
from.FlagOne ? Flag.One : Flag.Two,
from.FlagTwo ? Flag.One : Flag.Two,
from.FlagThree ? Flag.One : Flag.Two }

主要问题是你想要Flag.One,Flag.Two和Flag.Three来表示。