LINQ GroupBy从字符串转换为十进制然后返回字符串

时间:2018-01-08 01:17:10

标签: linq lambda group-by type-conversion

是否可以将字符串值转换为执行SUM或AVERAGE等聚合函数的LINQ表达式中的十进制值?

假设下面有一个银行账户集合的示例,我的目标是获得每个客户银行账户的平均值(如果他们有余额)。数据来自XML API,其中所有数据都以字符串形式读取。

public class BankAccount
{
  string Id{ get; set; }
  string CustomerId { get; set; }
  string Balance { get; set; }
}

示例数据......

{ Id = "1", CustomerId = "Bob", Balance = "1" }
{ Id = "2", CustomerId = "Bob", Balance = "2" }
{ Id = "3", CustomerId = "Sam", Balance = "4" }
{ Id = "4", CustomerId = "Sam", Balance = "" }
{ Id = "5", CustomerId = "Alice", Balance = "" }

LINQ分组表达式。有没有办法将Balance的值转换为十进制,以便可以在LINQ语句中获取平均值?我尝试了x => Decimal.Parse(x.Balance),但收到了Input string was not in a correct format错误。我只需要将Balance属性转换为十进制进行平均计算,因为结果将呈现为XML中的字符串。

同时,如果一个帐户没有列出余额(即它像Sams的第一个帐户和Alice上面唯一的帐户一样空白)那么我就不会希望平均值将该条目包含在平均值中,但我仍然希望将该帐户分组以供显示。

var groupedResults = allAccounts
                      .GroupBy(x => new {x.CustomerId, x.Balance})
                      .Select(g => new BankAccount {
                         CustomerId = g.Customer.Key.CustomerId,
                         Balance = g.Average(x => x.Balance)
                      }).ToList();

这些是我要找的结果:

{ CustomerId = "Bob", Balance = "1.5" }
{ CustomerId = "Sam", Balance = "4" }
{ CustomerId = "Alice", Balance = "" }

2 个答案:

答案 0 :(得分:1)

我认为要达到你想要的结果,你应该试试这个:

var groupedResults = allAccounts
                      .GroupBy(x =>x.CustomerId)
                      .Select(g => new BankAccount {
                         CustomerId = g.Key,
                         Balance = g.Where(x =>!string.IsNullOrEmpty(x.Balance))
                                    .Select(x =>(decimal?)decimal.Parse(x.Balance))
                                    .DefaultIfEmpty(null)
                                    .Average().ToString()
                      }).ToList();

首先只按CustomerId分组,不必在Balance包含Balance。然后,要获得平均值并避免错误解析包括确保from e in allAccounts group e by e.CustomerId into g let temp=g.Where(x =>!string.IsNullOrEmpty(x.Balance)) select new BankAccount(){CustomerId = g.Key, Balance =temp.Any()? temp.Average(x =>Decimal.Parse(x.Balance)).ToString():"" }; 不为空的条件。

使用查询语法的另一种方法:

(void)sendEmail:(NSString *)subject messageContent:(NSString *)body fileAttachment:(NSArray *)filePathArr fromWho:(NSString *)emailFrom toWho:(NSString *)emailTo{
/ create a Scripting Bridge object for talking to the Mail application */
MailApplication *mail = (MailApplication *)[[SBApplication alloc]initWithBundleIdentifier: @"com.apple.Mail"];
/ set ourself as the delegate to receive any errors */
/
[mail activate];
/ create a new outgoing message object */
MailOutgoingMessage *emailMessage = [[[mail classForScriptingClass:@"outgoing message"] alloc] initWithProperties:
                                     [NSDictionary dictionaryWithObjectsAndKeys:
                                      subject, @"subject",
                                      body, @"content",
                                      nil]];
/ Handle a nil value gracefully. */
if(!emailMessage)
    return;
/ add the object to the mail app  */
[[mail outgoingMessages] addObject: emailMessage];
/ set the sender, show the message */
emailMessage.sender = emailFrom;
emailMessage.visible = YES;
/ create a new recipient and add it to the recipients list */
MailToRecipient *theRecipient = [[[mail classForScriptingClass:@"to recipient"] alloc] initWithProperties:
                                 [NSDictionary dictionaryWithObjectsAndKeys:
                                  emailTo, @"address",
                                  nil]];
/ Handle a nil value gracefully. */
if(!theRecipient)
    return;
[emailMessage.toRecipients addObject: theRecipient];
/ add an attachment, if one was specified */
for(NSString *filePath in filePathArr){
    NSString *attachmentFilePath = filePath;
    if ( [attachmentFilePath length] > 0 ) {
        MailAttachment *theAttachment;
        / In Snow Leopard, the fileName property requires an NSString representing the path to the
         * attachment.  In Lion, the property has been changed to require an NSURL.   */
        SInt32 osxMinorVersion;
        Gestalt(gestaltSystemVersionMinor, &osxMinorVersion);
        / create an attachment object */
        if(osxMinorVersion >= 7)
            theAttachment = [[[mail classForScriptingClass:@"attachment"] alloc] initWithProperties:
                             [NSDictionary dictionaryWithObjectsAndKeys:
                              [NSURL fileURLWithPath:filePath], @"fileName",
                              nil]];
        else
        / The string we read from the text field is a URL so we must create an NSURL instance with it
         * and retrieve the old style file path from the NSURL instance. */
            theAttachment = [[[mail classForScriptingClass:@"attachment"] alloc] initWithProperties:
                             [NSDictionary dictionaryWithObjectsAndKeys:
                              [[NSURL URLWithString:attachmentFilePath] path], @"fileName",
                              nil]];
        / Handle a nil value gracefully. */
        if(!theAttachment)
            return;
        / add it to the list of attachments */
        [[emailMessage.content paragraphs] addObject: theAttachment];
    }
  }
  / send the message */
}

答案 1 :(得分:1)

decimal d;
var groupedResults = allAccounts.GroupBy(a => a.CustomerId)
    .Select(g => new BankAccount { CustomerId = g.Key, Balance = g.Average(b => 
        decimal.TryParse(b.Balance, out d) ? (decimal?)d : null).ToString() }).ToList();

.TryParse部分导致(decimal?)null表示无法解析的字符串,然后是ignored by .Average。此外,Alice的最后平均值为(decimal?)null,然后是""