【问题标题】:Sort by first column, after by second if first contains duplicates etc [closed]按第一列排序,如果第一个包含重复项,则按第二列排序[关闭]
【发布时间】:2022-01-04 02:00:38
【问题描述】:

我有一个简单的 .txt 文件,其中包含表格,其中列按制表符划分。因此,我需要从文件中读取数据并以排序方式写入另一个文件。我首先需要按第一列排序。如果它包含重复值,则应对第二列中的值进行排序(仅对第一列中的重复值进行排序),依此类推。 数字高于字母,数字按升序排列,字母按字母顺序排列。 所以,如果我有这样的文件

排序后我需要这个

我找到了这个How do I sort records in a text file using Java?,但是有没有有效的方法来实现剩余的排序逻辑,而不仅仅是第一列?

【问题讨论】:

  • 您的意思是“首先按第二个键排序,然后按第一个键;使用稳定排序”`?是什么让你坚持?请出示minimal reproducible example,说明您如何简单地按一键排序。

标签: java arrays sorting comparator


【解决方案1】:

所以,实际上你尝试通过它们的内容来比较,也就是说,每一行都可以表示为一个字符串数组,其中一些字符串应该作为数字进行比较。

所以,自定义比较器需要根据上述要求这样实现:

  • 数字应作为数字进行比较
  • 字符串应该按字母顺序比较
  • 数字在 个字符串之前(因此小于 个字符串)
private static int customCompare(String[] s1, String[] s2) {
    int res = 0;
    for (int i = 0, n = Math.min(s1.length, s2.length); res == 0 && i < n; i++) {
        Comparable e1 = convert(s1[i]);
        Comparable e2 = convert(s2[i]);
         
        if (e1 instanceof Double && e2 instanceof Double) {
            res = Double.compare((Double)e1, (Double)e2);
        } else if (e1 instanceof String && e2 instanceof String) {
            res = e1.compareTo(e2);
        } else {
            res = e1 instanceof Double ? -1 : 1;
        }
    }
    return res != 0 ? res : Integer.compare(s1.length, s2.length);
}

// utility method to check for numeric format and convert to Double if needed
private static Comparable convert(String s) {
    if (null == s || !s.matches("[-+]?(\\d+|\\d*\\.\\d+)")) {
        return s;
    }
    return Double.valueOf(s);
}

测试:

String[] data = {
    "-2.2\t2\t3\t4",
    "2.2\t12345q\t69\t-afq",
    "2.2\t12345q\t69\t-asdf",
    "-22\t1234234\tasdfasf\tasdgas",
    "-22\t-3\t4",
    "",
    "-1.1",
    " ",
    "qqqq\tq1.1",
    "qqqq\t0.1",
    "qqqq\t-1.1",
    "-22\t11\tabc"
};

Arrays.stream(data)
      .map(s -> s.split("\t")) // Stream<String[]> rows
      .sorted(MyClass::customCompare) // reference to customCompare method
      .map(arr -> String.join("\t", arr))
      .forEach(System.out::println);

输出:

-22 -3  4
-22 11  abc
-22 1234234 asdfasf asdgas
-2.2    2   3   4
-1.1
2.2 12345q  69  -afq
2.2 12345q  69  -asdf

 
qqqq    -1.1
qqqq    0.1
qqqq    q1.1

【讨论】:

    【解决方案2】:

    你可以试试下面的算法。

    1. 创建具有 4 个字符串字段的类 TableLine:rowOne、rowTwo、rowThree、rowFour(我想最大行数是 4?)。

    2. 从文件中读取行并将每一行放入 TableLine 对象中。结果应该是List&lt;TableLine&gt;

    3. 创建一个比较器:

      Comparator<TableLine> comparator
      = Comparator.comparing(TableLine::getRowOne)
                  .thenComparing(TableLine::getRowTwo)...
      

      等你需要考虑的所有行。

    4. 使用上面的比较器对您的列表进行排序。

    5. 写回文件

    【讨论】:

      猜你喜欢
      • 2016-11-07
      • 2016-07-19
      • 2018-10-07
      • 2017-06-17
      • 1970-01-01
      • 2018-11-23
      • 2012-02-28
      • 2021-05-03
      • 1970-01-01
      相关资源
      最近更新 更多