如何按两列对CSV文件进行排序?现在我能够按一列排序。我需要先按两列排序。怎么做?这是我用于按第一列排序的代码:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class Practice {
public static void main(String[] args) throws Exception {
BufferedReader reader = new BufferedReader(new FileReader("sample-input.csv"));
Map<String, List<String>> map = new TreeMap<String, List<String>>();
String line = reader.readLine();//read header
while ((line = reader.readLine()) != null) {
String key = getField(line);
List<String> l = map.get(key);
if (l == null) {
l = new LinkedList<String>();
map.put(key, l);
}
l.add(line);
}
reader.close();
FileWriter writer = new FileWriter("output.csv");
writer.write("Symbol, Exchange, Minimum, Average, Maximum, Total\n");
for (List<String> list : map.values()) {
for (String val : list) {
writer.write(val);
writer.write("\n");
}
}
writer.close();
}
private static String getField(String line) {
return line.split(",")[0];
// extract value you want to sort on
}
}
编辑:两列排序后的输出变为:
ABC,X,0.10,10
ABC,X,0.09,20
ABC,X,0.11,10
ABC,X,0.11,20
ABC,X,0.10,10
ABC,Y,0.09,10
ABC,Y,0.08,10
ABC,Z,0.12,15
ABC,Z,0.10,15
DEF,X,0.17,10
DEF,X,0.14,10
DEF,Y,0.15,15
DEF,Y,0.15,15
DEF,Y,0.17,15
DEF,Y,0.16,15
DEF,Y,0.17,15
DEF,Z,0.14,10
DEF,Z,0.15,10
我需要这样的输出:
ABC,X,0.09,0.11
ABC,X,0.09,0.11
ABC,X,0.09,0.11
ABC,X,0.09,0.11
ABC,X,0.09,0.11
ABC,Y,0.08,0.9
ABC,Y,0.08,0.9
ABC,Z,0.10,0.12
ABC,Z,0.10,0.12
DEF,X,0.14,0.17
DEF,X,0.14,0.17
DEF,Y,0.15,0.17
DEF,Y,0.15,0.17
DEF,Y,0.15,0.17
DEF,Y,0.15,0.17
DEF,Y,0.15,0.17
DEF,Z,0.14,0.15
DEF,Z,0.14,0.15
但是,我希望第三列显示X的最小值,然后显示Y的最小值,然后显示当前在第三列中显示的值的Z值。
答案 0 :(得分:4)
虽然创建充当域的适当表示的类通常是个好主意:在这种情况下,我不同意与评论。
读取CSV并按(String
内容)对一列或多列进行排序是一项非常通用的操作。它独立于域名。
可以实现一个Comparator
,只需在List<String>
的几个索引处选取字符串,并按字典顺序比较这些索引的值。使用此Comparator
,可以对从CSV文件中读取的任何List<List<String>>
进行排序。
这是一个简单的例子。它可用于根据任意列的字符串内容对任何 CSV文件进行排序。
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class MultiColumnCsvSort
{
private static final String COLUMN_SEPARATOR = ",";
public static void main(String[] args) throws Exception
{
InputStream inputStream = new FileInputStream("sample-input.csv");
List<List<String>> lines = readCsv(inputStream);
// Create a comparator that sorts primarily by column 0,
// and if these values are equal, by column 2
Comparator<List<String>> comparator = createComparator(0, 2);
Collections.sort(lines, comparator);
OutputStream outputStream = new FileOutputStream("output.csv");
String header = "Symbol, Exchange, Minimum, Average, Maximum, Total";
writeCsv(header, lines, outputStream);
}
private static List<List<String>> readCsv(
InputStream inputStream) throws IOException
{
BufferedReader reader = new BufferedReader(
new InputStreamReader(inputStream));
List<List<String>> lines = new ArrayList<List<String>>();
// Skip header
String line = reader.readLine();
while (true)
{
line = reader.readLine();
if (line == null)
{
break;
}
List<String> list = Arrays.asList(line.split(COLUMN_SEPARATOR));
lines.add(list);
}
return lines;
}
private static void writeCsv(
String header, List<List<String>> lines, OutputStream outputStream)
throws IOException
{
Writer writer = new OutputStreamWriter(outputStream);
writer.write(header+"\n");
for (List<String> list : lines)
{
for (int i = 0; i < list.size(); i++)
{
writer.write(list.get(i));
if (i < list.size() - 1)
{
writer.write(COLUMN_SEPARATOR);
}
}
writer.write("\n");
}
writer.close();
}
private static <T extends Comparable<? super T>> Comparator<List<T>>
createComparator(int... indices)
{
return createComparator(MultiColumnCsvSort.<T>naturalOrder(), indices);
}
private static <T extends Comparable<? super T>> Comparator<T>
naturalOrder()
{
return new Comparator<T>()
{
@Override
public int compare(T t0, T t1)
{
return t0.compareTo(t1);
}
};
}
private static <T> Comparator<List<T>> createComparator(
final Comparator<? super T> delegate, final int... indices)
{
return new Comparator<List<T>>()
{
@Override
public int compare(List<T> list0, List<T> list1)
{
for (int i = 0; i < indices.length; i++)
{
T element0 = list0.get(indices[i]);
T element1 = list1.get(indices[i]);
int n = delegate.compare(element0, element1);
if (n != 0)
{
return n;
}
}
return 0;
}
};
}
}
几年后更新:
如果您希望更灵活地处理各列的排序顺序,则有不同的选项。哪一个是“最好的”主要取决于你想如何“组装”实际的比较器 - 也就是说,你想如何定义哪个列应该在中排序订单。但是这里显示了一个简单的例子:
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class MultiColumnCsvSortExtended
{
private static final String COLUMN_SEPARATOR = ",";
public static void main(String[] args) throws Exception
{
InputStream inputStream = new FileInputStream("sample-input.csv");
List<List<String>> lines = readCsv(inputStream);
// Create a comparator that compares the elements from column 0,
// in ascending order
Comparator<List<String>> c0 = createAscendingComparator(0);
// Create a comparator that compares the elements from column 2,
// in descending order
Comparator<List<String>> c1 = createDesendingComparator(2);
// Create a comparator that compares primarily by using c0,
// and secondarily by using c1
Comparator<List<String>> comparator = createComparator(c0, c1);
Collections.sort(lines, comparator);
OutputStream outputStream = new FileOutputStream("output.csv");
String header = "Symbol, Exchange, Minimum, Average";
writeCsv(header, lines, outputStream);
}
private static List<List<String>> readCsv(
InputStream inputStream) throws IOException
{
BufferedReader reader = new BufferedReader(
new InputStreamReader(inputStream));
List<List<String>> lines = new ArrayList<List<String>>();
String line = null;
// Skip header
line = reader.readLine();
while (true)
{
line = reader.readLine();
if (line == null)
{
break;
}
List<String> list = Arrays.asList(line.split(COLUMN_SEPARATOR));
lines.add(list);
}
return lines;
}
private static void writeCsv(
String header, List<List<String>> lines, OutputStream outputStream)
throws IOException
{
Writer writer = new OutputStreamWriter(outputStream);
writer.write(header+"\n");
for (List<String> list : lines)
{
for (int i = 0; i < list.size(); i++)
{
writer.write(list.get(i));
if (i < list.size() - 1)
{
writer.write(COLUMN_SEPARATOR);
}
}
writer.write("\n");
}
writer.close();
}
@SafeVarargs
private static <T> Comparator<T>
createComparator(Comparator<? super T>... delegates)
{
return (t0, t1) ->
{
for (Comparator<? super T> delegate : delegates)
{
int n = delegate.compare(t0, t1);
if (n != 0)
{
return n;
}
}
return 0;
};
}
private static <T extends Comparable<? super T>> Comparator<List<T>>
createAscendingComparator(int index)
{
return createListAtIndexComparator(Comparator.naturalOrder(), index);
}
private static <T extends Comparable<? super T>> Comparator<List<T>>
createDesendingComparator(int index)
{
return createListAtIndexComparator(Comparator.reverseOrder(), index);
}
private static <T> Comparator<List<T>>
createListAtIndexComparator(Comparator<? super T> delegate, int index)
{
return (list0, list1) ->
delegate.compare(list0.get(index), list1.get(index));
}
}