2011-01-11 15 views
7

Me gusta la forma en que puedo tratar las listas en Python. Hace que cualquier solución de recursión parezca fácil y limpia. Por ejemplo, el problema típico de conseguir todas las permutaciones de elementos en una lista, en Python parece:¿Hay formas más elegantes de manejar listas en Java? (Python VS Java)

def permutation_recursion(numbers,sol): 
    if not numbers: 
     print "this is a permutation", sol 
    for i in range(len(numbers)): 
     permutation_recursion(numbers[:i] + numbers[i+1:], sol + [numbers[i]]) 

def get_permutations(numbers): 
    permutation_recursion(numbers,list()) 

if __name__ == "__main__": 
    get_permutations([1,2,3]) 

me gusta la forma en que pueda sencillo conseguir nuevos casos de listas modificadas haciendo cosas como numbers[:i] + numbers[i+1:] o sol + [numbers[i]]

Si trato de código exactamente la misma en Java, que parece:

import java.util.ArrayList; 
import java.util.Arrays; 

class rec { 
    static void permutation_recursion(ArrayList<Integer> numbers, ArrayList<Integer> sol) { 
     if (numbers.size() == 0) 
      System.out.println("permutation="+Arrays.toString(sol.toArray())); 
     for(int i=0;i<numbers.size();i++) { 
      int n = numbers.get(i); 

      ArrayList<Integer> remaining = new ArrayList<Integer>(numbers); 
      remaining.remove(i); 

      ArrayList<Integer> sol_rec = new ArrayList<Integer>(sol); 
      sol_rec.add(n); 

      permutation_recursion(remaining,sol_rec); 
     } 
    } 
    static void get_permutation(ArrayList<Integer> numbers) { 
     permutation_recursion(numbers,new ArrayList<Integer>()); 
    } 
    public static void main(String args[]) { 
     Integer[] numbers = {1,2,3}; 
     get_permutation(new ArrayList<Integer>(Arrays.asList(numbers))); 
    } 
} 

para crear el mismo recursividad que tengo que hacer:

ArrayList<Integer> remaining = new ArrayList<Integer>(numbers); 
remaining.remove(i); 

ArrayList<Integer> sol_rec = new ArrayList<Integer>(sol); 
sol_rec.add(n); 

Lo cual es bastante feo y empeora para soluciones más complejas. Al igual que en this example

Así que mi pregunta es ... ¿hay algún operador incorporado o funciones auxiliares en la API de Java que haría esta solución más "Ptónica"?

+3

Siempre hay Jython :) – Seth

+2

El 'más' en el título es superfluo - la pregunta debería ser si hay alguna forma ordenada de trabajar con listas en Java. Y afaik, no, no hay ninguno. –

Respuesta

8

Pero esta es la razón por Martin Odersky creado Scala. Incluso ha dicho que uno de sus objetivos para Scala es que sea el Python del mundo de Java. Scala compila el bytecode de Java e interactúa fácilmente con clases compiladas en Java.

Si esa no es una opción, puede echar un vistazo al Commons Collection Library.

+0

+1 por ser preciso. – Nishant

+4

Yo diría que Jython es el Python del mundo de Java ;-). –

2

Puede usar la función clone() en Listas para obtener una copia superficial de ellas. De esta forma, no tendrá que crear una instancia de un nuevo Objeto usted mismo, sino que puede usar la copia.

ArrayList<Integer> remaining = remaining.clone().remove(i); 

Aparte de eso, no, java no tiene tales operadores para las listas.

+0

No compilará ... – whiskeysierra

0

Hola 1 puede usar la pila, que será más útil.

2 el bucle se puede escribir así: para (Número n: número)

1

Apache Commons resuelve muchos de estos tipos de problemas. Eche un vistazo a ArrayUtils para hacer rebanadas. Java no tiene una gran cantidad de azúcar sintáctico, como lo hacen los lenguajes de scripting por varias razones.

1

Diferentes idiomas requieren diferentes estilos. Tratar de lograr mylist[:i] + mylist[i+1:] en java es como usar un martillo con un tornillo. Sí, puedes hacerlo, pero no es muy ordenado. Creo que el equivalente podría ser algo como ArrayList temp = new ArrayList(list); temp.remove(index);

Creo que lo siguiente lleva a cabo la misma tarea, pero lo hace de una manera ligeramente diferente, pero no sufre problemas de legibilidad. En lugar de crear una nueva lista, modifica la lista, la transmite y devuelve la lista a su estado anterior cuando regresa la llamada recursiva.

import java.util.Arrays; 
import java.util.List; 
import java.util.ArrayList; 

public class Permutation { 

    public static void main(String[] args) { 

     List<List<Integer>> result = permutations(
             Arrays.asList( 
              new Integer[] {1,2,3})); 

     for (List<Integer> permutation : result) { 
     System.out.println(permutation); 
     } 
    } 


    public static <T> List<List<T>> permutations(List<T> input) { 
     List<List<T>> out = new ArrayList<List<T>>(); 
     permutationsSlave(input, new ArrayList<T>(), out); 
     return out; 
    } 

    public static <T> void permutationsSlave(List<T> input, 
      ArrayList<T> permutation, List<List<T>> result) { 

     if (input.size() == chosen.size()) { 
     result.add(new ArrayList<T>(permutation)); 
     return; 
     } 

     for (T obj : input) { 
     if (!permutation.contains(obj)) { 
      permutation.add(obj); 
      permutationsSlave(input, permutation, result); 
      permutation.remove(permutation.size()-1); 
     } 
     } 

    } 
} 

La forma de pitón puede parecer fácil y más limpio, pero la capacidad de mirar limpia a menudo oculta el hecho de que la solución es bastante ineficiente (para cada nivel de recursividad se crea 5 nuevas listas).

Pero entonces mi propia solución tampoco es tremendamente eficiente: en lugar de crear múltiples objetos nuevos, realiza comparaciones redundantes (aunque parte de esto podría aliviarse mediante el uso de acumuladores).

Cuestiones relacionadas