【问题标题】:How can apply TryParse on multiple propertied with fluent LINQ?如何使用流利的 LINQ 在多个属性上应用 TryParse?
【发布时间】:2018-01-23 05:11:58
【问题描述】:

我有一个对象列表。对象是这样的

public class GenericRecord
{
    public string GroupName { get; set; }
    public DateTime CreatedAt { get; set; }
    public string Col1 { get; set; }
    public string Col2 { get; set; }
    public string Col3 { get; set; }
    public float ConvertedCol1 { get; set; }
    public float ConvertedCol3 { get; set; }
    public float ConvertedCol3 { get; set; }
}

我想使用 fluent LINQ 解析 Col1Col2Col3 属性,然后对它们求和。

我想做这样的事情

IEnumerable<GenericRecord> records = ...;
var summaries = records.Select(x => new GenericRecord 
{
   float.TryParse(x.Col1, out ConvertedCol1),
   float.TryParse(x.Col2, out ConvertedCol2),
   float.TryParse(x.Col3, out ConvertedCol3),
   GroupName => x.GroupName
}).GroupBy(x => x.GroupName)
.Select(x => new {
   GroupName = x.Key,
   Total1 = x.Sum(y => y.ConvertedCol1),
   Total2 = x.Sum(y => y.ConvertedCol2),
   Total3 = x.Sum(y => y.ConvertedCol3),
   Count = x.Count()
}).ToList();

但是,linq 中的 float.TryParse 语法不起作用。

如何使用 Fluent LINQ 解析多个列?

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    将处理放入方法中:

    private static GenericRecord ConvertGenericRecord(GenericRecord x) {
        float c1, c2, c3;
        float.TryParse(x.Col1, out c1);
        float.TryParse(x.Col2, out c2);
        float.TryParse(x.Col3, out c3);
        return new GenericRecord {
            ConvertedCol1 = c1;
            ConvertedCol2 = c2;
            ConvertedCol3 = c3;
            GroupName = x.GroupName
        };
    }
    

    使用方法如下:

    var summaries = records
        .Select(ConvertGenericRecord)
        .GroupBy(x => x.GroupName)
        .Select(x => new {
            GroupName = x.Key,
            Total1 = x.Sum(y => y.ConvertedCol1),
            Total2 = x.Sum(y => y.ConvertedCol2),
            Total3 = x.Sum(y => y.ConvertedCol3),
            Count = x.Count()
        }).ToList();
    

    TryParse 的调用在 EF 或 LINQ2SQL 中不起作用。如果您正在从 DB 读取,请在调用 ConvertGenericRecord 之前添加 AsEnumerable()ToList()

    如果必须在 DB 端进行转换,请将 TryParse 替换为 SqlFunctions.StringConvert(...) (detailed Q&A)。

    【讨论】:

      【解决方案2】:

      您不能那样使用对象初始化器语法。它需要左侧的属性名称,而不是引用。

      也许GenericRecord 可以有一个构造函数并为您进行转换,或者让属性为您转换它。

      【讨论】:

      • records 对象是从数据库中填充的。我可以转换它的唯一另一种方法是向该对象添加一个函数,该函数将为我处理 tryparse。但是,我将无法在 LINQ 中使用我的自定义函数来对解析的数据求和,除了使用构造函数之外还有其他方法吗?
      【解决方案3】:

      如果您查看 Generic Record 类的对象初始化器,则对象初始化器中不支持操作:

      var record = new GenericRecord
      {
          GroupName = "Group",
          CreatedAt = DateTime.Now,
          Col1 = "Col1",
          Col2 = "Col2",
          Col3 = "Col3",
      };
      

      你的问题可能很明显,如果我是你,我会将此功能推送到通用记录的构造函数中:

      public GenericRecord(string col1, string col2, string col3, string groupName)
      {
         float convertedVal1;
         if (float.TryParse(col1, out convertedVal1))
         {
            ConvertedCol1 = convertedVal1;
         }
      }
      

      现在你的 Linq 语句会容易得多:

      var summaries = records.Select(x => new GenericRecord(x.Col1, x.Col2, x.Col3, x.GroupName))
                  .GroupBy(x => x.GroupName)
                  .Select(x => new {
                      GroupName = x.Key,
                      Total1 = x.Sum(y => y.ConvertedCol1),
                      Total2 = x.Sum(y => y.ConvertedCol2),
                      Total3 = x.Sum(y => y.ConvertedCol3),
                      Count = x.Count()
                  }).ToList();
      

      编辑: 如果您不介意不安全的强制转换,另一种可能的解决方案是使用 float.Parse:

      https://msdn.microsoft.com/en-us/library/2thct5cb(v=vs.110).aspx

      var summaries = records.Select(x => new GenericRecord
                  {
                      ConvertedCol1 = float.Parse(x.Col1),
                      ConvertedCol2 = float.Parse(x.Col2),
                      ConvertedCol3 = float.Parse(x.Col3),
                      GroupName = x.GroupName
                  })
                  .GroupBy(x => x.GroupName)
                  .Select(x => new {
                      GroupName = x.Key,
                      Total1 = x.Sum(y => y.ConvertedCol1),
                      Total2 = x.Sum(y => y.ConvertedCol2),
                      Total3 = x.Sum(y => y.ConvertedCol3),
                      Count = x.Count()
                  }).ToList();
      

      希望对你有帮助

      【讨论】:

        猜你喜欢
        • 2021-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-18
        • 2014-10-21
        • 2014-11-20
        • 1970-01-01
        • 2023-03-26
        相关资源
        最近更新 更多