csv文件有两列CATEGORY和MILES,我必须在python中的Business CATEGORY下找到%MILE


CATEGORY MILES
Business  5.1
Business  4.6
Business  3.9
Personal  8.5
Business  3.7
Personal  6.2
Personal  11

这是摘录自excel表格

因此,您有一个CSV格式的文本文件,您需要读取它,将其转换为[Category,Miles]的组合,并且您希望每个Category"%英里数";,不管是什么。

Category Miles
X       1
X       4
X       2
Y       3

我认为你想要:;类别X具有70%的里程,类别Y也具有30%的里程";。

要解决这个问题,最好把你的问题切成小块。

  • 给定一个字符串fileName,将文件读取为文本
  • 给定CSV格式的字符串,将其转换为BusinessMiles类的序列
  • 给定BusinessMiles的序列,将其转换为"%"英里数";,根据上述定义

将问题分割成更小的部分有几个优点:

  • 每件作品的功能都会更容易理解
  • 更容易进行单元测试
  • 更容易更改,例如,如果您不是从CSV文件而是从数据库读取,或者如果您不是从不CSV字符串而是从XML或JSON文件读取
  • 最重要的是:你将能够将这些片段重新用于其他任务,比如:";我的几行是关于商业的">

可重用性得到了最清楚的证明,因为其中几个部分已经存在,并且可以自由使用:读取文件并将文件转换为CSV。

为此,请考虑使用Nuget Package CSV帮助程序。易于使用,用途广泛,因此是最常用的CSV包之一。

因此,假设您有读取CSV文件并将其转换为BusinessMiles 序列的过程

enum Category
{
Business,
Personal,
}
class BusinessMile          // TODO: invent proper name
{
public Category Category {get; set;}
public Decimal Miles {get; set;}
}

通过使用枚举,您可以确定在阅读CSV后不会有任何不正确的类别。为将来的版本添加新的类别将很容易。如果你在编译时不知道哪些类别是允许的,可以考虑使用字符串。这有可能导致有人出现键入错误,从而导致一个全新的类别,而没有人注意到";人员;而不是";"个人";

IEnumerable<BusinessMile> ReadBusinessMiles(string csvText)
{
// use CSVHelper to convert the csvText to the sequence
}
IEnumerable<BusinessMile> ReadBusineMilesFile(string fileName)
{
// either use CSVHelper, or read the file and call the other method
}

在这之后,你的问题将很容易:

string fileName = ...
IEnumerable<BusinessMile> businessMiles = ReadBusinesMilesFile(fileName);

制作具有相同类别的BusinessMiles群组:

var categoryGroups = businessMiles.GroupBy(
businessMile => businessMile.Category,
// parameter resultSelector: for every Category, and all BusinessMiles
// that have this Category to make one new
(category, businessMilesInThisCategory) => new
{
Category = category,
TotalMiles = businesMilesInThisCategory
.Select(businessMile => businessMile.Miles)
.Sum(),
});

所以现在你有了:

Category TotalMiles
X         7
Y         3

如果你真的想知道百分比,你需要得到所有类别的所有里程的总和(=6(,并用总里程除以这个

var totalMiles = categorieGroups.Select(group => group.TotalMiles).Sum();
var result = categoryGroups.Select(group => new
{
Category = group.Category,
TotalMilesPercentage = 100.0M * group.TotalMiles / totalMiles,
})

在我对BusinessMiles的定义中,Miles是十进制数。如果您的里程数是整数,请小心转换。

最新更新