2011-01-11 9 views
7

Podobał mi się sposób, w jaki mogę traktować listy w Pythonie. Wykonuje dowolne rozwiązanie rekursji, aby wyglądać łatwo i czysto. Na przykład typowy problem uzyskania wszystkich permutacji elementów na liście, w Pythonie wygląda następująco:Czy istnieją bardziej eleganckie sposoby obsługi list w Javie? (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]) 

zrobić jak sposób mogę prosty uzyskać nowe instancje zmodyfikowanych listach wykonując takie rzeczy jak numbers[:i] + numbers[i+1:] lub sol + [numbers[i]]

Jeśli staram się dokładnie taki sam kod w Javie, to wygląda:

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

aby utworzyć taką samą rekursji należy zrobić:

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

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

Co jest dość brzydkie i pogarsza się w przypadku bardziej złożonych rozwiązań. Podobnie jak w this example

Moje pytanie brzmi: czy są jakieś wbudowane funkcje operatorów lub pomocników w API Javy, które sprawiłyby, że to rozwiązanie byłoby bardziej "Pythoniczne"?

+3

Zawsze jest Jython :) – Seth

+2

"Więcej" w tytule jest zbędne - powinno być pytanie, czy istnieje jakikolwiek sposób na pracę z listami w Javie. A afaik, nie - nie ma. –

Odpowiedz

8

nr

Ale to dlaczego Martin Odersky stworzony Scala. Powiedział nawet, że jednym z jego celów dla Scala jest to, że jest to Python świata Java. Scala kompiluje się do kodu bajtowego Java i łatwo współdziała z klasami skompilowanymi w Javie.

Jeśli to nie jest opcja, możesz rzucić okiem na Commons Collection Library.

+0

+1 za dokładność. – Nishant

+4

Twierdzę, że Jython jest Pythonem świata Java ;-). –

2

Możesz użyć funkcji clone() na listach, aby uzyskać ich płytką kopię. W ten sposób nie będziesz musiał sam tworzyć nowego obiektu, ale możesz po prostu użyć jego kopii.

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

Poza tym nie, java nie ma takich operatorów dla list.

+0

Nie skompiluję ... – whiskeysierra

0

Witam 1 możesz użyć stosu, który będzie bardziej przydatny.

2 do pętli mogą być napisane tak: dla (liczba n: liczba)

1

Apache Commons rozwiązuje wiele tego rodzaju problemów. Zajrzyj do ArrayUtils, aby zrobić krojenie. Java nie ma dużo syntaktycznego cukru, jak języki skryptów z różnych powodów.

1

Różne języki wymagają różnych stylów. Próba wykonania mylist[:i] + mylist[i+1:] w języku Java jest jak użycie młotka ze śrubą. Tak, możesz to zrobić, ale nie jest to bardzo uporządkowane. Wydaje mi się, że odpowiednik może być podobny do: ArrayList temp = new ArrayList(list); temp.remove(index);

Sądzę, że poniższe czynności wykonują to samo zadanie, ale robią to w nieco inny sposób, ale nie mają problemów z czytelnością. Zamiast tworzyć nową listę, modyfikuje listę, przekazuje ją i zwraca listę do poprzedniego stanu, gdy wywołanie rekursywne powraca.

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

    } 
} 

Sposób pyton może wyglądać na łatwe i czystsze, ale umiejętność wyglądać czyste często ukrywa fakt, że rozwiązanie jest zupełnie nieefektywne (na każdym poziomie rekurencji tworzy 5 nowych list).

Ale moje własne rozwiązanie również nie jest zbyt wydajne - zamiast tworzyć wiele nowych obiektów, wykonuje nadmiarowe porównania (choć niektóre z nich można złagodzić za pomocą akumulatorów).