0

次のような csv データセットがあります。

A, 10, USA
B,30, UK
C,4,IT
A,20,UK
B,10,USA

この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でこれを実現したい。Linq を使用して C# でこれを行いました。

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();  
        }

各名前の合計マイレージ値を取得して平均を計算する良い方法を探しています。

4

4 に答える 4

1

C# 開発者として、linq の機能を見逃さないようにするのは難しい場合があります。しかし、Farlan が提案したように、次のようなことができます。

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);
    }
}
于 2013-03-17T21:52:46.670 に答える
0

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]);
}
于 2013-03-17T19:58:16.000 に答える
0

There are quite a few ways to do this, some long-winded approaches, some shorter. The issue is that Java can be very verbose for doing simple tasks, so the better approaches can be a bit uglier.

The example below shows you exactly how to achieve this, par the printing. Bear in mind however, it might not be the best approach but I feel its more of the easier ones to read and comprehend.

    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();

The steps involved are simple:

Step 1 - Read the file.

By passing a File into the Scanner object, you set the target parsing to the File and not the console. Using the very neat hasNextLine() method, you can continually read each line until no more exist. Each line is then split by a comma, and stored in a String array for reference.

Step 2 - Associating the data.

As you want to cumulatively add the integers together, you need a way to associate already passed in letters with the numbers. A heavyweight but clean way of doing this is to use a HashMap. The Key which it takes is going to be a String, specifically A B or C. By taking advantage of the fact the Key is unique, we can use the O(1) containsKey(String) method to check if we've already read in the letter. If its new, add it to the HashMap and save the number with it. If however, the letter has been seen before, we find the old value, add it with the new one and overwrite the data inside the HashMap.

All you need to do now is print out the data. Feel free to take a different approach, but I hope this is a clear example of how you CAN do it in Java.

于 2013-03-17T22:33:21.313 に答える