3

我正在做一个需要显示收入高于平均水平的人的列表的项目。源数据是一个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>();

以下是我如何确定一个人的收入是否高于平均水平。如果一个人的收入高于平均水平,我将idandincome的临时实例添加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 和收入应该在哪里。有人可以告诉我我做错了什么以及如何在消息框中显示列表值吗?

4

3 回答 3

1

在你的问题结束时,你问:我如何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());

有关预期输出的完整工作示例,请参见以下(和在线演示)。

预期产出

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);
            }
        }
    }
}
于 2014-07-04T16:18:21.677 回答
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.");
于 2013-05-31T23:55:05.563 回答
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 调用中,您需要将 aboveAverage 替换为

aboveAverage.Aggregate((a,b) => a.ToString() + Enviroment.NewLine + b.ToString())

应该让它正确显示。

抱歉格式化,我在手机上。

于 2013-05-31T23:55:18.317 回答