【问题标题】:Idiomatic "First Last" => "Last, First" in JavaJava 中惯用的“First Last” => “Last, First”
【发布时间】:2014-08-21 23:58:35
【问题描述】:

我主要是一名 Python 程序员,学习一些 Java。我需要一个函数来将包含“First Last”形式的名称的字符串转换为“Last, First”(我还需要它来处理单个名称:“Cher”=>“Cher”和 First Middle Last:“John F. Kennedy" => "Kennedy, John F.") 我开始考虑像在 Python 中那样解决它:

def tolastfirst(astring):
    parts = astring.split()
    return parts[-1] + ", " + " ".join(parts[:-1])

字符串切片和列表拆分和连接在 Python 中非常常见和简洁,这是我首先想到的。翻译成 Java 是这样的:

public static String toLastFirst(String firstLast) {
    List<String> parts = Arrays.asList(firstLast.split(" "));
    if (parts.size() > 1) {
        String last = parts.get(parts.size() - 1);
        List<String> frontParts = parts.subList(0, parts.size() - 1);
        String front = org.apache.commons.lang.StringUtils.join(frontParts.toArray(), " ");
        return last + ", " + front;
    } else {
        return firstLast;
    }
}

所以这似乎是不必要的复杂,而且从代码中可能很明显,我不明白使用数组与列表的原因和原因。从 Array 转换为 List 并再次转换回来似乎很愚蠢,所以我尝试了这个:

public static String toLastFirst(String firstLast) {
    String[] parts = firstLast.split(" ");
    if (parts.length > 1) {
        String last = parts[parts.length - 1];
        String[] frontParts = Arrays.copyOfRange(parts, 0, parts.length - 1);
        String front = org.apache.commons.lang.StringUtils.join(frontParts, " ");
        return last + ", " + front;
    } else {
        return firstLast;
    }
}

最后,我问了一位真正了解 Java 的同事,他建议他更有可能只查找最后一个空格并将字符串切分,跳过整个 List/Array 业务:

public static String toLastFirst(String firstLast) {
    if (firstLast.indexOf(" ") != -1) {
        Integer lastSpace = firstLast.lastIndexOf(" ");
        String first = firstLast.substring(0, lastSpace);
        String last = firstLast.substring(lastSpace, firstLast.length());
        return last + ", " + first;
    } else {
        return firstLast;
    }
}

我的问题是:

  • 我是否有正确的直觉从使用列表切换到数组?
  • 我的同事建议直接进行字符串操作是在 Java 中解决这个问题的最惯用的方法吗?
  • 字符串操作方法是否比列表/数组方法更有效(内存、速度?)?

我主要对第二个问题感兴趣;我想学习像本地人而不是像 Python expat 那样编写 Java。

【问题讨论】:

    标签: java string sorting substring


    【解决方案1】:

    你可以用replaceAll()做这个更短的时间:

    public static String toLastFirst(String firstLast) {
        return firstLast.replaceAll("(.*) (.*)", "$2, $1");
    }
    

    这应该与您的实现完全一样。如果字符串中包含空格,则表达式将匹配,并切换第一部分和第二部分,并添加,。如果不包含空格,则字符串保持不变。

    【讨论】:

    • 我编辑了这个问题,注意我的用例包括像“Cher”=>“Cher”这样的单个名称以及中间名的名称:“Philip Seymour Hoffman”=>“Hoffman, Philip Seymour” ...您的解决方案是否涵盖这些情况?
    • 将正则表达式更改为 "(.*) (.*)" 可以满足我的需要。酷。
    • @ben:是的,我正要这么说。 :) 使第一部分变得贪婪确保唯一的交换是在最后一个空格。
    【解决方案2】:

    一般来说,当您不需要调整大小时,数组会更容易使用。您当然希望避免混合使用数组和列表,尝试使用其中一种但不要混合使用。

    直接操作是我解决这个问题的方法,因为你只有两半的特定情况。 @Keppil 的答案可能是最简洁的 Java 解决方案。

    直接的 String 操作会稍微快一些,因为 Array/List 不需要创建、初始化、更新等。不过,绝对意义上的差异很小。

    【讨论】:

      【解决方案3】:

      你可以这样做:

      public static String toLastFirst(String firstLast) {
          //split on one ore more space chars
          String[] data = firstLast.split("\\s+");
          //need to check length of array etc.
          return data[1] + ", " + data[0];  //build new string
      }
      

      【讨论】:

      • 这是否涵盖用例“Philip Seymour Hoffman”=>“Hoffman, Philip Seymour”?
      • 跟我的第二次尝试很相似吧?
      • @benauthor - 对于这个问题,考虑将datai&lt;data.length-1 循环到i=0,构建一个用StringBuilder 初始化的StringBuilder 对象
      猜你喜欢
      • 2020-10-11
      • 2018-01-26
      • 2017-12-07
      • 2011-10-05
      • 1970-01-01
      • 1970-01-01
      • 2020-09-21
      • 2018-12-31
      • 2011-01-22
      相关资源
      最近更新 更多