2011-01-11 12 views
7

Mi piace il modo in cui posso trattare le liste in Python. Fa qualsiasi soluzione di ricorsione per sembrare semplice e pulita. Per esempio il problema tipico di ottenere tutte le permutazioni di elementi in un elenco, in Python assomiglia:Esistono modi più eleganti per gestire gli elenchi in 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]) 

mi piace il modo in cui posso semplice ottenere nuovi casi di elenchi modificati facendo le cose come numbers[:i] + numbers[i+1:] o sol + [numbers[i]]

Se provo a codice esattamente lo stesso in Java, sembra che:

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))); 
    } 
} 

per creare lo stesso ricorsione ho bisogno di fare:

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

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

Che è piuttosto brutto e peggiora per soluzioni più complesse. Come in this example

Quindi la mia domanda è ... ci sono operatori o funzioni di supporto nell'API Java che renderebbero questa soluzione più "Pythonic"?

+3

C'è sempre Jython :) – Seth

+2

Il 'più' nel titolo è superfluo - la domanda dovrebbe essere se c'è un modo pulito di lavorare con elenchi in Java di sorta. E afaik, no - non c'è nessuno. –

risposta

8

No.

Ma questo è il motivo per Martin Odersky creato Scala. Ha anche detto che uno dei suoi obiettivi per Scala è che sia il Python del mondo Java. Scala si compila nel bytecode Java e si interfaccia facilmente con le classi compilate Java.

Se questa non è un'opzione, è possibile dare un'occhiata allo Commons Collection Library.

+0

+1 per essere precisi. – Nishant

+4

Direi che Jython è il Python del mondo Java ;-). –

2

È possibile utilizzare la funzione clone() negli elenchi per ottenere una copia superficiale di essi. In questo modo non dovrai istanziare un nuovo oggetto da solo, ma puoi semplicemente usare la copia.

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

A parte questo, no, java non dispone di tali operatori per le liste.

+0

Non verrà compilato ... – whiskeysierra

0

Hi 1 è possibile utilizzare lo stack, che sarà più pratico.

2 il ciclo for si può scrivere in questo modo: per (Numero n: numeri)

1

Apache Commons risolve un sacco di questi tipi di problemi. Date un'occhiata a ArrayUtils per fare affettare. Java non ha molto zucchero sintattico come i linguaggi di scripting per vari motivi.

1

Diverse lingue richiedono stili diversi. Cercando di realizzare mylist[:i] + mylist[i+1:] in java è come usare un martello con una vite. Sì, puoi farlo, ma non è molto ordinato. Credo che l'equivalente potrebbe essere qualcosa come ArrayList temp = new ArrayList(list); temp.remove(index);

Credo che quanto segue assolva lo stesso compito, ma lo fa in un modo leggermente diverso, ma non ha problemi di leggibilità. Invece di creare un nuovo elenco, modifica l'elenco, lo inoltra e restituisce l'elenco al suo stato precedente al ritorno della chiamata ricorsiva.

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); 
     } 
     } 

    } 
} 

Il modo pitone può sembrare semplice e pulito, ma la capacità di guardare pulito nasconde spesso il fatto che la soluzione è abbastanza inefficiente (per ogni livello di ricorsione crea 5 nuovi elenchi).

Ma la mia soluzione non è nemmeno così efficiente: invece di creare più nuovi oggetti esegue confronti ridondanti (anche se alcuni di questi potrebbero essere alleviati dall'uso di accumulatori).

Problemi correlati