2012-05-23 13 views
5

Mam listę elementów (tj. Ciągi), które należy sortować/filtrować.Filtrowanie elementów z zestawu w języku Java

Wynik końcowy powinien być nie zawierać żadnych duplikatów (łatwe), będę je wszystkie w zestawie. Więc mam teraz zestaw strun.

dodatkowych wyjaśnień ..

że również metodę A i X, które oblicza wartość różnicy pomiędzy dwa łańcuchy (stosując odległość Levenstein).

Pytanie:

Przed włożeniem nowego String string do mojego Zestaw set Chcę sprawdzić Odległość Levenshteina stosując metodę x między string i innych ciągów z set a jeśli x zwrotów >=3 niż powinienem nie dodawaj tego.

Jaki jest mój najlepszy sposób na zrobienie tego? Z wyjątkiem iteracyjnego korytka set dla każdego string do wstawienia?

+1

Utwórz własną metodę dodawania lokalnego, która sprawdza to, a następnie dodaje ją do zestawu, jeśli pomyślnie przeszła test. – jn1kk

+0

Jest mało prawdopodobne, że istnieje rozwiązanie, które robi to bez potencjalnej iteracji przez cały zestaw, ponieważ zasadniczo chcesz znaleźć ciąg, który jest najdalej od tego, który wstawiasz i testujesz odległość. Pocieszeniem jest to, że możesz wykonać zwarcie po znalezieniu dużej odległości. Ostatnią rzeczą, na którą należy zwrócić uwagę, jest to, że wynik zależy od zamówienia reklamowego: '345 34567 12345' odrzuci '12345', ale' 345 12345 34567' odrzuci '34567' (To po prostu dziwne, że tego chcesz). – trutheality

Odpowiedz

2

Iterowanie przez Set będzie najlepszym rozwiązaniem, ponieważ nie ma żadnej wbudowanej implementacji Set, która pomogłaby zawęzić możliwości.

1

Podczas tworzenia zestawu można użyć niestandardowego komparatora. W twoim komparatorze zwracasz, że dwa ciągi są takie same, jeśli są takie same (jak w przypadku regularnych reguł porównywania ciągów znaków) lub jeśli ich odległość Levenstein spełnia twoje kryteria.

Kiedy twój comapator mówi, że dwa ciągi są takie same, nowy ciąg nie jest wstawiany do zestawu. (Zauważ, że oznacza to, że efekt końcowy łańcucha może zależeć od kolejności wstawiania)

aktualizacji: Adresowanie komentarze o łącznej zamawiającego:

Korzystanie komparator jak ten przedstawiony powyżej może sprawić, że endresult zależne zgodnie z kolejnością wstawiania (jak wspomniano powyżej), podobnie jak każde inne rozwiązanie zastosowane w kryteriach odległości Levensteina nie określa porządku całkowitego.

OTOH, gdy ciąg przejdzie test nierówności i zostanie wstawiony do zestawu, żaden inny ciąg w zestawie nie będzie porównywać z tym samym, więc ciągi w zestawie będą używać ich naturalnej kolejności ciągów, co ma Zdefiniuj całkowitą kolejność, więc nie ma dalszych niespójności w wewnętrznych operacjach zestawu (np. sortowanie).

+1

Jak można to zrobić w całości? Nie widzę tego. –

+0

Użycie kryterium odległości w Levenstein nie daje całkowitej wartości zamówienia (np. Set000> get000 == tit011 == set000) – Attila

+0

Um ... użycie odległości dla komparatora dałoby niespójne zamówienie. Dlatego należy użyć zamieszania dotyczącego tego, dlaczego sugerujesz użycie komparatora. – trutheality

2

Grałem z moim pomysłem, jak to zrobić. Nie mogę wymyślić sposób to zrobić bez jakiejkolwiek iteracji.

Załóżmy, że masz metodę o nazwie distance(String,String):int, która zwraca podaną odległość między dwoma ciągami znaków.

String x = "Obi-wan"; //this is the item subject to eval addition 
List<String> items = new ArrayList<String>(asList("Luke","Yoda","Anakin")); 
if (items.filter(s -> distance(s, x) >= 3).getFirst() == null) { 
    items.add(x); 
} 

Jeśli używasz JDK8 Preview można to zrobić w krótkim czasie, używając dokładnie powyższy kod. Metoda Iterables.getFirst() nie będzie iterować całego zbioru, ale tylko do momentu znalezienia pierwszego elementu spełniającego kryteria.

W przeciwnym razie prawdopodobnie będziesz musiał zaimplementować interfejs predykatu i metodę filtrowania.

interface Predicate<T> { 
    public boolean eval(T o); 
} 

public static void main(String[] args) { 
    final String x = "Obi-wan"; //this is the item subject to eval addition 
    List<String> items = new ArrayList<String>(asList("Luke","Yoda","Anakin")); 
    Predicate<String> p = new Predicate<String>() { 
     public boolean eval(String s){ 
      return distance(s, x) >= 3; 
     } 
    }; 
    if(filter(items, p).isEmpty()){ 
     items.add(x); 
    } 
} 

public static <T> List<T> filter(List<? extends T> items, Predicate<? super T> predicate){ 
    List<T> destiny = new ArrayList<T>(); 
    for(T item : items){ 
     if(predicate.eval(item){ 
      destiny.add(item); 
     } 
    } 
    return destiny; 
} 

Można również zatrzymać filtrowanie po znalezieniu pierwszego elementu spełniającego podane kryteria.

Powiązane problemy