Java: obtener el último elemento después de dividir

133

Estoy usando el método de división de cadenas y quiero tener el último elemento. El tamaño de la matriz puede cambiar.

Ejemplo:

String one = "Düsseldorf - Zentrum - Günnewig Uebachs"
String two = "Düsseldorf - Madison"

Quiero dividir las cadenas anteriores y obtener el último elemento:

lastone = one.split("-")[here the last item] // <- how?
lasttwo = two.split("-")[here the last item] // <- how?

No sé los tamaños de las matrices en tiempo de ejecución :(

n00ki3
fuente
1
En lugar de esto, puede obtener subcadenas e indexof.
Surendheran
@SurendarKannan La respuesta más votada tiene un ejemplo de eso, con lastIndexOf.
Adam Jensen

Respuestas:

173

Guarde la matriz en una variable local y use el lengthcampo de la matriz para encontrar su longitud. Reste uno para tener en cuenta que está basado en 0:

String[] bits = one.split("-");
String lastOne = bits[bits.length-1];

Advertencia: si la cadena original está compuesta solo por el separador, por ejemplo "-"o "---", bits.lengthserá 0 y esto arrojará una ArrayIndexOutOfBoundsException. Ejemplo: https://onlinegdb.com/r1M-TJkZ8

Jon Skeet
fuente
27
Solo tenga en cuenta que en el caso de que la cadena de entrada esté vacía, la segunda instrucción arrojará una excepción de "índice fuera de límites".
Stephen C
77
no, si divide una cadena vacía, devolverá una matriz que contiene un elemento que es la cadena vacía en sí.
Panthro
Si la cadena original está compuesta solo por el separador, por ejemplo "-"o "---", bits.lengthserá 0 y esto arrojará una ArrayIndexOutOfBoundsException. Ejemplo: onlinegdb.com/r1M-TJkZ8
Dário
Vea la respuesta de Denis Bazhenov para una solución que no arroja ArrayIndexOutOfBoundsException: stackoverflow.com/a/1181976/4249576
Dário
250

O podrías usar el lastIndexOf()método en String

String last = string.substring(string.lastIndexOf('-') + 1);
Denis Bazhenov
fuente
16
Creo que esta solución requiere menos recursos.
ufk
¿Esto no arrojará un IndexOutOfBoundsExceptionsi stringno contiene '-'?
Jared Beck
66
No, @JaredBeck, no lo hace. Pero devuelve la cadena completa, que puede o no ser lo que desea. Podría ser mejor comprobar que el personaje en el que estás dividiendo existe primero en la cadena.
james.garriss
1
Pero eso arrojará un IndexOutOfBoundsExceptionif stringcontiene '-'en la última posición
damgad
8
@damgad, no lo hará. lastIndexOf será la longitud de la cadena - 1. Entonces, terminará con la cadena vacía
Denis Bazhenov
31

Puede usar la clase StringUtils en Apache Commons:

StringUtils.substringAfterLast(one, "-");
Ranosama
fuente
23

usando un método auxiliar simple pero genérico como este:

public static <T> T last(T[] array) {
    return array[array.length - 1];
}

puedes reescribir:

lastone = one.split("-")[..];

como:

lastone = last(one.split("-"));
dfa
fuente
3
Una cosa que debe hacer es proteger el método last () contra matrices vacías o podría obtener IndexOutOfBoundsException.
Denis Bazhenov el
@dotsid, por otro lado, podría ser mejor lanzar una ArrayIndexOutOfBoundsException en lugar de devolver nulo aquí, ya que detectará el error donde ocurre en lugar de causar el problema.
Emil H
1
@dotsid, me gustaría dejar esta responsabilidad a la persona que llama, ocultando excepciones de tiempo de ejecución es peligroso
dfa
Muy agradable, y, por supuesto, first()y nth(T[array], int n)está muy bien hecha de esto.
Peter Ajtai
12
String str = "www.anywebsite.com/folder/subfolder/directory";
int index = str.lastIndexOf('/');
String lastString = str.substring(index +1);

Ahora lastStringtiene el valor"directory"

Zar E Ahmer
fuente
7

Con guayaba :

final Splitter splitter = Splitter.on("-").trimResults();
assertEquals("Günnewig Uebachs", Iterables.getLast(splitter.split(one)));
assertEquals("Madison", Iterables.getLast(splitter.split(two)));

Splitter, Iterables

palacsint
fuente
7

Reunimos todas las formas posibles juntos !!


Mediante el uso lastIndexOf()y substring()métodos deJava.lang.String

// int firstIndex = str.indexOf( separator );
int lastIndexOf = str.lastIndexOf( separator );
String begningPortion = str.substring( 0, lastIndexOf );
String endPortion = str.substring( lastIndexOf + 1 );
System.out.println("First Portion : " + begningPortion );
System.out.println("Last  Portion : " + endPortion );

split()Java SE 1.4 . Divide el texto proporcionado en una matriz.

String[] split = str.split( Pattern.quote( separator ) );
String lastOne = split[split.length-1];
System.out.println("Split Array : "+ lastOne);

Java 8 secuencial ordenado flujo de una matriz.

String firstItem = Stream.of( split )
                         .reduce( (first,last) -> first ).get();
String lastItem = Stream.of( split )
                        .reduce( (first,last) -> last ).get();
System.out.println("First Item : "+ firstItem);
System.out.println("Last  Item : "+ lastItem);

Apache Commons Lang jar «org.apache.commons.lang3.StringUtils

String afterLast = StringUtils.substringAfterLast(str, separator);
System.out.println("StringUtils AfterLast : "+ afterLast);

String beforeLast = StringUtils.substringBeforeLast(str, separator);
System.out.println("StringUtils BeforeLast : "+ beforeLast);

String open = "[", close = "]";
String[] groups = StringUtils.substringsBetween("Yash[777]Sam[7]", open, close);
System.out.println("String that is nested in between two Strings "+ groups[0]);

Guava: Bibliotecas de Google Core para Java. «Com.google.common.base.Splitter

Splitter splitter = Splitter.on( separator ).trimResults();
Iterable<String> iterable = splitter.split( str );
String first_Iterable = Iterables.getFirst(iterable, "");
String last_Iterable = Iterables.getLast( iterable );
System.out.println(" Guava FirstElement : "+ first_Iterable);
System.out.println(" Guava LastElement  : "+ last_Iterable);

Secuencias de comandos para la plataforma Java «Ejecutar Javascript en la JVM con Rhino / Nashorn

  • Rinoceronte «Rhino es una implementación de código abierto de JavaScript escrita completamente en Java. Por lo general, está incrustado en aplicaciones Java para proporcionar secuencias de comandos a los usuarios finales. Está integrado en J2SE 6 como el motor de secuencias de comandos Java predeterminado.

  • Nashorn es un motor de JavaScript desarrollado en el lenguaje de programación Java por Oracle. Se basa en la máquina Da Vinci y se ha lanzado con Java 8.

Guía del programador de secuencias de comandos Java

public class SplitOperations {
    public static void main(String[] args) {
        String str = "my.file.png.jpeg", separator = ".";
        javascript_Split(str, separator);
    }
    public static void javascript_Split( String str, String separator ) {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");

        // Script Variables « expose java objects as variable to script.
        engine.put("strJS", str);

        // JavaScript code from file
        File file = new File("E:/StringSplit.js");
        // expose File object as variable to script
        engine.put("file", file);

        try {
            engine.eval("print('Script Variables « expose java objects as variable to script.', strJS)");

            // javax.script.Invocable is an optional interface.
            Invocable inv = (Invocable) engine;

            // JavaScript code in a String
            String functions = "function functionName( functionParam ) { print('Hello, ' + functionParam); }";
            engine.eval(functions);
            // invoke the global function named "functionName"
            inv.invokeFunction("functionName", "function Param value!!" );

            // evaluate a script string. The script accesses "file" variable and calls method on it
            engine.eval("print(file.getAbsolutePath())");
            // evaluate JavaScript code from given file - specified by first argument
            engine.eval( new java.io.FileReader( file ) );

            String[] typedArray = (String[]) inv.invokeFunction("splitasJavaArray", str );
            System.out.println("File : Function returns an array : "+ typedArray[1] );

            ScriptObjectMirror scriptObject = (ScriptObjectMirror) inv.invokeFunction("splitasJavaScriptArray", str, separator );
            System.out.println("File : Function return script obj : "+ convert( scriptObject ) );

            Object eval = engine.eval("(function() {return ['a', 'b'];})()");
            Object result = convert(eval);
            System.out.println("Result: {}"+ result);

            // JavaScript code in a String. This code defines a script object 'obj' with one method called 'hello'.
            String objectFunction = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }";
            engine.eval(objectFunction);
            // get script object on which we want to call the method
            Object object = engine.get("obj");
            inv.invokeMethod(object, "hello", "Yash !!" );

            Object fileObjectFunction = engine.get("objfile");
            inv.invokeMethod(fileObjectFunction, "hello", "Yashwanth !!" );
        } catch (ScriptException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static Object convert(final Object obj) {
        System.out.println("\tJAVASCRIPT OBJECT: {}"+ obj.getClass());
        if (obj instanceof Bindings) {
            try {
                final Class<?> cls = Class.forName("jdk.nashorn.api.scripting.ScriptObjectMirror");
                System.out.println("\tNashorn detected");
                if (cls.isAssignableFrom(obj.getClass())) {
                    final Method isArray = cls.getMethod("isArray");
                    final Object result = isArray.invoke(obj);
                    if (result != null && result.equals(true)) {
                        final Method values = cls.getMethod("values");
                        final Object vals = values.invoke(obj);
                        System.err.println( vals );
                        if (vals instanceof Collection<?>) {
                            final Collection<?> coll = (Collection<?>) vals;
                            Object[] array = coll.toArray(new Object[0]);
                            return array;
                        }
                    }
                }
            } catch (ClassNotFoundException | NoSuchMethodException | SecurityException
                    | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            }
        }
        if (obj instanceof List<?>) {
            final List<?> list = (List<?>) obj;
            Object[] array = list.toArray(new Object[0]);
            return array;
        }
        return obj;
    }
}

Archivo JavaScript « StringSplit.js

// var str = 'angular.1.5.6.js', separator = ".";
function splitasJavaArray( str ) {
  var result = str.replace(/\.([^.]+)$/, ':$1').split(':');
  print('Regex Split : ', result);
  var JavaArray = Java.to(result, "java.lang.String[]");
  return JavaArray;
  // return result;
}
function splitasJavaScriptArray( str, separator) {
    var arr = str.split( separator ); // Split the string using dot as separator
    var lastVal = arr.pop(); // remove from the end
    var firstVal = arr.shift(); // remove from the front
    var middleVal = arr.join( separator ); // Re-join the remaining substrings

    var mainArr = new Array();
    mainArr.push( firstVal ); // add to the end
    mainArr.push( middleVal );
    mainArr.push( lastVal );

    return mainArr;
}

var objfile = new Object();
objfile.hello = function(name) { print('File : Hello, ' + name); }
Yash
fuente
Atención al usar Java 8 Stream ejemplo. si divide por espacio ("") una Cadena como esta: Basic (hay un espacio final), obtendrá Basiccomo último elemento.
belgoros
5

Como él estaba pidiendo hacerlo todo en la misma línea usando split, sugiero esto:

lastone = one.split("-")[(one.split("-")).length -1]  

Siempre evito definir nuevas variables en la medida de lo posible, y me parece una muy buena práctica.

azerafati
fuente
Pero eso arrojará un IndexOutOfBoundsExceptionif si la cadena no contiene-
Stoinov
@Stoinov, en realidad no lo hará. puedes probarlo! ;)
azerafati
1
Se ejecuta dividido dos veces y, a veces, puede ser demasiado lento. Por lo tanto, esta es una alternativa a la respuesta aceptada para cambiar la velocidad de almacenamiento.
Paul
@PaulZhang sí, es cierto, aunque la división es muy rápida en sí misma, pero esta es una opción única por solicitud de OP
azerafati
3

¿Quiere decir que no conoce los tamaños de las matrices en tiempo de compilación? En tiempo de ejecución se pueden encontrar por el valor de lastone.lengthy lastwo.length.

Sean AO Harney
fuente
3

En java 8

String lastItem = Stream.of(str.split("-")).reduce((first,last)->last).get();
Hadi J
fuente
1

Supongo que quieres hacer esto en línea. Es posible (aunque un poco de malabares = ^)

new StringBuilder(new StringBuilder("Düsseldorf - Zentrum - Günnewig Uebachs").reverse().toString().split(" - ")[0]).reverse()

tadaa, una línea -> el resultado que desea (si divide en "-" (espacio menos espacio) en lugar de solo "-" (menos) también perderá el espacio molesto antes de la partición = ^) así que "Günnewig Uebachs" en lugar de "Günnewig Uebachs" (con un espacio como primer personaje)

Bonito extra -> no necesita archivos JAR adicionales en la carpeta lib para que pueda mantener su aplicación ligera.

irJvV
fuente
1

También puedes usar java.util.ArrayDeque

String last = new ArrayDeque<>(Arrays.asList("1-2".split("-"))).getLast();
Maxim Sidorov
fuente