当前位置: 首页 > 面试题库 >

如何用Java中的两列对csv文件进行排序?

须衡虑
2023-03-14
问题内容

如何按两列对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。


问题答案:

尽管创建类作为 域的 适当表示通常是一个好主意:在这种情况下,我 不同意 注释。

读取CSV并按String一列或多列的内容进行排序是非常通用的操作。并且它独立于域。

可以实现一个Comparator简单地从a的多个索引处选择字符串List<String>并按字典顺序比较这些索引处的值的a
。使用此工具Comparator,可以对List<List<String>>从CSV文件读取的任何内容进行排序。

这是一个简单的例子。它可用于根据任意列的字符串内容对 任何 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));
    }

}


 类似资料:
  • 问题内容: 嗨,我正在尝试读取未排序的文件,并让Java对CSV数据文件的一列进行排序,并将这些结果打印到新文件中。我在此网站上搜索时借用了该解决方案,因为我认为这对我想要完成的工作非常理想。我有282行数据,形式为 这是在csv文件中。当我使用上面的代码时,它在sorted_marks.txt中只给我一行,就像这样 我相信它甚至都没有排序。 我希望将新文件中的所有结果根据其用户ID排序,但没有别

  • 问题内容: 这是我的代码,它有效!但我希望能够根据名称,大小,修改日期等对文件列表进行排序 问题答案: 您可以定义许多不同的类来进行不同的比较,例如: 然后,您只需将它们换出: 要么

  • 问题内容: 我有一个带有单词列表的文本文件,我需要使用Java按字母顺序对其进行排序。单词位于单独的行上。 我将如何处理,将它们读入数组列表,然后进行排序? 问题答案: 这是一个简单的四步过程,其中Stackoverflow问题解决了四个步骤中的三个: 阅读每一行并将其转换为Java String 将每个Java字符串存储在一个数组中(不要认为您需要引用它。) 排序数组 写出数组中的每个Java字

  • 问题内容: 当我们使用命令时,文件以一种排序的方式显示其内容,如果我不想得到任何种类的输出,而是一个经过排序的文件怎么办? 问题答案: 您可以使用文件重定向来重定向排序后的输出: 或者你也可以使用,排序的选项,以指示相同的输入和输出文件: 注意: 一个常见的错误是试图将输出重定向到相同的输入文件(例如)。这不起作用,因为外壳正在进行重定向(而不是 sort(1) 程序),并且在为 sort(1)

  • 问题内容: 首先,我发布此内容是因为当我在寻找以下问题的解决方案时,我在stackoverflow上找不到该解决方案。因此,我希望在此处增加一些知识库。 我需要处理目录中的某些文件,并且需要对文件进行数字排序。我在wiki.python.org上找到了一些有关排序的示例(尤其是使用模式),并将它们放在一起: 我对Python还是很陌生,想问一下社区是否可以对此进行任何改进:缩短代码(删除),性能,