是否可以将字符串值转换为执行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 = "" }
答案 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
,然后是""
。