我正在开展一个项目,需要显示收入高于平均水平的人员名单。源数据为List<IncomeData>
(id
是此人的唯一ID):
public struct IncomeData
{
public string id;
public double household;
public income;
}
public double belowAverage = 0, total, belowAveragePercent;
IncomeData surveyStruct;
List<IncomeData> surveyList = new List<IncomeData>();
List<string> aboveAverage = new List<string>();
以下是我如何判断一个人的平均收入是否高于平均水平。如果一个人的收入高于平均水平,我会将id
和income
从surveyStruct
的临时实例添加到上述平均字符串值列表中:
//Determine poverty.
if (surveyStruct.income - 3480 * surveyStruct.household <= 6730)
{
belowAverage += 1;
}
else if (surveyStruct.income - 3480 * surveyStruct.household >= 6730)
{
aboveAverage.Add(surveyStruct.id);
aboveAverage.Add(surveyStruct.income.ToString());
}
以下是在消息框中显示所需信息的代码。 (此处也添加了aboveAverage
列表。)
private void reportsToolStripMenuItem_Click(object sender, EventArgs e)
{
//Display reports 1, 2, and 3.
MessageBox.Show("Your Entry:\nID Code: " + surveyStruct.id +
"\nHousehold: " + surveyStruct.household.ToString() +
" people\nIncome: " + surveyStruct.income.ToString("C") +
"\n\nPeople Above Average:\n" + aboveAverage +
"\n\nAnd " + belowAveragePercent + "% of people are below average.");
}
现在,问题出在这里:我没有看到消息框中的值列表,而是看到System.Collections.Generic.List
`1[System.String]
其中的ID和收入高于平均水平的人应该是。有人可以告诉我我做错了什么以及如何在消息框中显示列表值?
答案 0 :(得分:0)
StringBuilder是一个选择:
StringBuilder aboveAverage = new StringBuilder();
//Determine poverty.
if (surveyStruct.income - 3480 * surveyStruct.household <= 6730)
{
belowAverage += 1;
}
else if (surveyStruct.income - 3480 * surveyStruct.household >= 6730)
{
aboveAverage.Append(string.Format("id: %s, income: %s\n",
surveyStruct.id, surveyStruct.income.ToString());
}
你需要为字符串构建器使用ToString(),如下所示:
MessageBox.Show("Your Entry:\nID Code: " + surveyStruct.id + "\nHousehold: " + surveyStruct.household.ToString() + " people\nIncome: " + surveyStruct.income.ToString("C") + "\n\nPeople Above Average:\n" + aboveAverage.ToString() + "\n\nAnd " + belowAveragePercent + "% of people are below average.");
如果您将AboveAverage作为列表保留,则可以使用join进行此操作:
string.Join(aboveAverage,Environment.NewLine);
在您当前的代码中 - 但这看起来不太好。
你也可以用Linq做,你想看到吗?
好的,这是一个性感的单行版本:(所有问题应该有一行linq答案):
(使用和缩进不计算,它们只是为了使代码更具可读性!)
using NL = Environment.NewLine;
string indent = " ";
MessageBox.Show(
"Your Entry:" + NL +
"ID Code: " + surveyStruct.id + NL +
"Household: " + surveyStruct.household.ToString() + " people" + NL +
"Income: " + surveyStruct.income.ToString("C") + NL + NL +
"People Above Average:" + NL +
indent + string.Join(NL+indent,
surveyList.Where(s => (s.income - 3480) * s.household >= 6730)
.Select(s => "ID: "+s.id+" $"+s.income.ToString).ToArray()) + NL +
"And " + (surveyList.Where(s => ((s.income - 3480) * s.household) <= 6730).Count() / surveyList.Count()) * 100 + "% of people are below average.");
答案 1 :(得分:0)
首先,将AboveAverage设为List<IncomeData>
,并将匹配的IncomeDatas添加到该列表中。
然后,您需要为自定义结构定义ToString
,如下所示:
public override void string ToString()
{
return string.Format("The id is {0}, the household is {1} and the income is {2}.", id, household, income);
}
然后,在MessageBox.Show调用中,您需要用
替换aboveAverageaboveAverage.Aggregate((a,b) => a.ToString() + Enviroment.NewLine + b.ToString())
应该让它正确显示。
抱歉格式化,我在移动设备上。
答案 2 :(得分:0)
在问题的最后,您问:如何在消息框中显示List<IncomeData>
?
因此,您的问题的核心是将您的值列表转换为字符串,以便您可以将该字符串作为参数传递给MessageBox.Show()
。
LINQ 扩展方法Enumerable.Aggregate()为此问题提供了理想的解决方案。假设您的List<IncomeData>
看起来像这样(为了简洁起见,我省略了household
字段):
var incomes = new List<IncomeData>() {
new IncomeData("abc0123", 15500),
new IncomeData("def4567", 12300),
new IncomeData("ghi8901", 17100)
};
以下LINQ查询会将List<IncomeData>
转换为string
:
string message = incomes.
Select(inc => inc.ToString()).
Aggregate((buffer, next) => buffer + "\n" + next.ToString());
为了不需要调用Select()
,您可以改为使用Enumerable.Aggregate()的双参数版本。此方法还允许您将标题指定为累加器的种子值:
string message2 = incomes.
Aggregate(
"Income data per person:",
(buffer, next) => buffer + "\n" + next.ToString());
这相当于下面的参数类型已经明确:
string message = incomes.
Aggregate<IncomeData, string>(
"Income data per person:",
(string buffer, IncomeData next) => buffer + "\n" + next.ToString());
请参阅以下内容(和online demo),了解其预期输出之前的完整工作示例。
预期输出
Income data per person:
Id: abc0123, Income:15500
Id: def4567, Income:12300
Id: ghi8901, Income:17100
演示计划
using System;
using System.Collections.Generic;
using System.Linq;
namespace LinqAggregateDemo
{
public class Program
{
public static void Main(string[] args)
{
var incomes = new List<IncomeData>() {
new IncomeData("abc0123", 15500),
new IncomeData("def4567", 12300),
new IncomeData("ghi8901", 17100)
};
string message = incomes.
Select(inc => inc.ToString()).
Aggregate((buffer, next) => buffer + "\n" + next.ToString());
Console.WriteLine("Income data per person:\n" + message);
}
public struct IncomeData
{
public readonly string Id;
public readonly int Income;
public IncomeData(string id, int income)
{
this.Id = id;
this.Income = income;
}
public override string ToString()
{
return String.Format(
"Id: {0}, Income:{1}",
this.Id,
this.Income);
}
}
}
}