用Java从集合中提取数据
我有一个csv数据集,如下所示:用Java从集合中提取数据,java,linq,csv,Java,Linq,Csv,我有一个csv数据集,如下所示: A, 10, USA B,30, UK C,4,IT A,20,UK B,10,USA CSVReader reader = new CSVReader(new FileReader(filename)); java.util.List<String[]> content = reader.readAll(); Map<String, Group> groups = new HashMap<>();
A, 10, USA
B,30, UK
C,4,IT
A,20,UK
B,10,USA
CSVReader reader = new CSVReader(new FileReader(filename));
java.util.List<String[]> content = reader.readAll();
Map<String, Group> groups = new HashMap<>();
for(String[] row : content)
{
String Name = row[0];
String Miles = row[1];
System.out.printf("%s has ran %s miles %n", Name, Miles);
if (groups.containsKey(Name)){
groups.get(Name).Add(Double.valueOf(Miles));
} else {
Group g = new Group();
g.Add(Double.valueOf(Miles));
groups.put(Name, g);
}
}
reader.close();
for (String name : groups.keySet())
{
System.out.println(name + " ran " + groups.get(name).total() + " with avg of " + groups.get(name).average());
}
}
class Group {
private List<Double> miles;
public Group()
{
miles = new ArrayList<>();
}
public Double total(){
double sum = 0;
for (Double mile : miles)
{
sum += mile;
}
return sum;
}
public Double average(){
if (miles.size() == 0)
return 0d;
return total() / miles.size();
}
public void Add(Double m){
miles.add(m);
}
}
我想阅读此csv行并提供以下输出:
A has ran 30 miles with average of 15.
B has ran 30 miles with average of 20.
C has ran 4 miles with average of 4.
我想用Java实现这一点。我已经在C#中使用Linq完成了这项工作:
var readlines = File.ReadAllLines(filename);
var query = from lines in readlines
let data = lines.Split(',')
select new
{
Name = data[0],
Miles = data[1],
};
var values = query.GroupBy(x => new {x.Name}).Select(group => new { Person = group.Key, Events = group.Sum(g =>Convert.ToDouble(g.Miles)) ,Count = group.Count() });
我希望在Java中实现这一点,我不确定是否可以在不使用任何第三方库的情况下实现这一点?有什么想法吗?
到目前为止,我的代码在Java中是这样的:
CSVReader reader = new CSVReader(new FileReader(filename));
java.util.List<String[]> content = reader.readAll();
String[] row = null;
for(Object object:content)
{
row = (String[]) object;
String Name = row[0];
String Miles = row[1];
System.out.printf("%s has ran %s miles %n",Name,Miles);
}
reader.close();
}
CSVReader reader=new CSVReader(new FileReader(filename));
java.util.List content=reader.readAll();
字符串[]行=null;
用于(对象:内容)
{
行=(字符串[])对象;
字符串名称=行[0];
字符串英里数=行[1];
System.out.printf(“%s已运行%s英里%n”,名称,英里);
}
reader.close();
}
我正在寻找一种很好的方法来获得每个名字的总milage值,以计算平均值 使用Java的BufferedReader类:
BufferedReader in = new BufferedReader(new FileReader("your.csv"));
String line;
while ( (line = in.readLine()) != null) {
String [] fields = line.split(",");
System.out.println(fields[0] + " has ran " + fields[1] + " miles with average " + fields[2]);
}
作为一名C#开发者,有时很难不错过linq的特性。但正如Farlan建议的那样,你可以这样做:
A, 10, USA
B,30, UK
C,4,IT
A,20,UK
B,10,USA
CSVReader reader = new CSVReader(new FileReader(filename));
java.util.List<String[]> content = reader.readAll();
Map<String, Group> groups = new HashMap<>();
for(String[] row : content)
{
String Name = row[0];
String Miles = row[1];
System.out.printf("%s has ran %s miles %n", Name, Miles);
if (groups.containsKey(Name)){
groups.get(Name).Add(Double.valueOf(Miles));
} else {
Group g = new Group();
g.Add(Double.valueOf(Miles));
groups.put(Name, g);
}
}
reader.close();
for (String name : groups.keySet())
{
System.out.println(name + " ran " + groups.get(name).total() + " with avg of " + groups.get(name).average());
}
}
class Group {
private List<Double> miles;
public Group()
{
miles = new ArrayList<>();
}
public Double total(){
double sum = 0;
for (Double mile : miles)
{
sum += mile;
}
return sum;
}
public Double average(){
if (miles.size() == 0)
return 0d;
return total() / miles.size();
}
public void Add(Double m){
miles.add(m);
}
}
CSVReader reader=new CSVReader(new FileReader(filename));
java.util.List content=reader.readAll();
映射组=新的HashMap();
for(字符串[]行:内容)
{
字符串名称=行[0];
字符串英里数=行[1];
System.out.printf(“%s已运行%s英里%n”,名称,英里);
if(组。容器(名称)){
groups.get(Name).Add(Double.valueOf(Miles));
}否则{
g组=新组();
g、 加上(双倍价值(英里));
组。put(名称,g);
}
}
reader.close();
for(字符串名称:groups.keySet())
{
System.out.println(name+“ran”+groups.get(name).total()+,平均值为“+groups.get(name).average());
}
}
班级{
私人列表里程;
公共组()
{
迈尔斯=新阵列列表();
}
公共双总额(){
双和=0;
用于(双英里:英里)
{
总和+=英里;
}
回报金额;
}
公众双倍平均{
如果(英里数大小()==0)
返回0d;
返回总计()/英里.size();
}
公共空间添加(双m){
英里。加上(m);
}
}
有很多方法可以做到这一点,有些是冗长的方法,有些是较短的方法。问题是Java在执行简单任务时可能非常冗长,因此更好的方法可能会有点难看
下面的例子说明了如何实现这一点,就像打印一样。但请记住,这可能不是最好的方法,但我觉得它更容易阅读和理解
final File csvFile = new File("filename.csv");
final Scanner reader = new Scanner(csvFile);
final Map<String, Integer> info = new HashMap<>(); //Store the data
//Until there is are no more lines, continue
while (reader.hasNextLine()) {
final String[] data = reader.nextLine().split(","); // data[0] = A. [1] = 10. [2] = USA
final String alpha = data[0];
if (!info.containsKey(alpha)) {
info.put(alpha, Integer.parseInt(data[1]));
} else {
int miles = info.get(alpha);
info.put(alpha, miles + Integer.parseInt(data[1]));
}
}
reader.close();
final File csvFile=新文件(“filename.csv”);
最终扫描仪阅读器=新扫描仪(csvFile);
最终映射信息=新HashMap()//存储数据
//在没有更多行之前,继续
while(reader.hasNextLine()){
最后一个字符串[]data=reader.nextLine().split(“,”);//数据[0]=A[1]=10[2]=USA
最终字符串alpha=数据[0];
如果(!info.containsKey(alpha)){
info.put(alpha,Integer.parseInt(数据[1]);
}否则{
int miles=信息获取(alpha);
info.put(alpha,miles+Integer.parseInt(数据[1]);
}
}
reader.close();
所涉及的步骤很简单:
步骤1-读取文件。
通过将文件
传递到扫描仪
对象,可以将目标解析设置为文件
,而不是控制台。使用非常简洁的hasNextLine()
方法,您可以连续读取每一行,直到不再存在为止。然后,每行用逗号分隔,并存储在字符串数组中以供参考
步骤2-关联数据。
当您想要将整数累加在一起时,需要一种将已经以字母形式传递的数字关联起来的方法。一种重量级但干净的方法是使用HashMap
。它所使用的键
将是一个字符串,特别是a
B
或C
。通过利用键
是唯一的这一事实,我们可以使用O(1)
containsKey(String)
方法来检查我们是否已经阅读了这封信。如果是新的,请将其添加到HashMap
中,并保存该号码。但是,如果以前见过该字母,我们会找到旧值,将其与新值一起添加,并覆盖HashMap
中的数据
你现在需要做的就是把数据打印出来。请随意选择不同的方法,但我希望这是一个清晰的示例,说明如何在Java中实现这一点。也许您可以尝试以下Java库: 它不使用任何getter/setter来处理数据,因此比LINQ更灵活 在您的情况下,文件“D:/input.csv”有3列:
NAME,MILES,COUNTRY
A, 10, USA
B,30, UK
C,4,IT
A,20,UK
B,10,USA
查询代码为:
final QModel raw = QNew.modelCSV("D:/input.csv")
.debug(-1);//print out what read from CSV
raw.query()
.selectAs("OUTPUT",
"CONCAT(NAME,' has ran ',SUM(MILES),' miles with average of ',MEAN(MILES),'.')")
.groupBy("NAME")
.result().debug(-1)//print out the result
.to().fileCSV("D:/output.csv", "UTF-8");//write to another CSV file
问题不是解析数据,我已经用opencsv很好地解析了数据。要找到平均值,我必须将数据分组到名称字段周围,找到英里数,将它们相加,除以名称字段重复的次数,得到平均值。这就是C#代码所做的,我正在寻找一个类似Java的简洁解决方案。然后使用一个HashMap,键作为名称,值作为数字。好的,我实现了它,但是如何将数据围绕一个值分组,比如如何将milage围绕名称值分组?你编译了这个吗?如何在构造函数中使用ArrayList()并将列表作为属性?我修复了这段代码,对于Java 1.6和Java 1.7,这段代码的编写方式略有不同。这段代码给了我另一个喜欢C#的好理由。您没有在标记中指定版本,所以我假设为1.7。为1.6:)填写缺少的类型谢谢您的尝试,但我想知道这个解决方案对我有什么好处?我在那里写的代码已经以一种非常简单和好的方式完成了您的代码所做的事情。T