2017-01-29 3 views
0

Я написал этот фрагмент кода, чтобы проверить, что список строк полностью содержится в другом, и в этом случае удалить список.Проверка списка строк, полностью содержащихся в другом списке строк

public static void main(String[] args) { 
    LinkedList<String> l1 = new LinkedList<String>(); 
    LinkedList<String> l2 = new LinkedList<String>(); 
    l1.add("Cc"); 
    l1.add("Dd"); 
    l2.add("Cc"); 
    l2.add("Dd"); 
    l2.add("Ee"); 
    LinkedList<LinkedList<String>> l = new LinkedList<LinkedList<String>>(); 
    l.add(l1); 
    l.add(l2); 
    System.out.println("OUTPUT: " + filterSublist(l)); 

} 

static List<LinkedList<String>> filterSublist(LinkedList<LinkedList<String>> l) { 
    List<LinkedList<String>> uniq = new LinkedList<LinkedList<String>>(l); 
    l.forEach(elem -> uniq.removeIf(x -> !x.equals(elem) && elem.contains(x))); 
    return uniq; 
} 

Функция filterSubList должна возвращать список список строк, который не имеет списков, которые полностью содержатся в других списках. В примере мы имеем:

  • Список 1: "Cc, Dd"
  • Список 2: "Cc, Dd, Ee"

Поскольку список 1 целиком содержится в списке 2, функция должна возвращать список списков, который содержит только список 2. Но когда я запускаю программу, которую я получил вывод, который представляет собой список, который содержит как:

OUTPUT: [[Cc, Dd], [Cc, Dd, Ee]] 

Это неправильно. Есть ли ошибка в функции filterSubList?

+0

Есть ли причина не использовать метод 'equals()' для проверки ** равенства ** двух «списков»? –

+0

Я не знаю, есть ли лучший способ. Что ты предлагаешь? –

+0

Ну, вы можете использовать метод 'equals()', который бы возвращал 'true', если два сравниваемых списка равны. Для примера 'System.out.println (list1.equals (list2))'. Но обратите внимание, что порядок содержания имеет значение. Если вам не нужен заказ, вы можете использовать 'HashSet' @Walrider –

ответ

1

Вы проверяете один список (объект), содержащий другой список (объект). Новый список будет отведенное по-разному в памяти всякий раз, когда создается новый объект, вместо проверки на объекты внутри с containsAll:

Попробуйте вместо этого:

static List<LinkedList<String>> filterSublist(LinkedList<LinkedList<String>> l) { 
List<LinkedList<String>> uniq = new LinkedList<LinkedList<String>>(l); 
l.forEach(elem -> uniq.removeIf(x -> !x.equals(elem) && elem.containsAll(x))); 
return uniq; 
} 

В случае Рене поднял некоторые вопросы, имеющие отношение к OP , вот реализация, которая в значительной степени следует за его руководством, по-другому.

static List<LinkedList<String>> filterSublistAlternate(LinkedList<LinkedList<String>> l) { 
boolean[] removed = new boolean[ l.size() ]; 
outer: for(int i=0; i< l.size() ; i++) 
    inner: for(int j=0; j< l.size() ; j++) 
    { 
     if(i != j) 
     if(l.get(j).containsAll(l.get(i))) 
     { 
      System.out.println(i+" and "+j); 
      if(l.get(i).size() == l.get(j).size()) 
       if(removed[i] == removed[j] && !removed[i]) 
        removed[i] = true; 
       else 
        continue outer; 
      else 
      { 
       removed[i] = true; 
       continue outer; 
      } 

     } 
    } 

for(int i=removed.length-1; i>=0 ; i--) 
    if(removed[i]) 
     l.remove(i); 

return l; 
} 
+0

У этого решения есть проблема, что 'uniq' может содержать один и тот же список несколько раз из-за использования' equals'. –

+0

Equals используется так, чтобы тот же список не сравнивался с самим собой. – dev8080

+0

Точно из-за 'equals' результат может быть неправильным, содержащим дубликаты. Просто добавьте еще l3 = ["Cc", "Dd", "Ee"] в l и посмотрите на результат. –

0

Я предлагаю решение ниже, как это:

  • больше памяти эффективной, поскольку она не дублировать первоначальный список
  • более правильно, поскольку она действительно проверяет подсписков (а не только один элемент существование)
  • более правильный, поскольку это удаляет дубликаты из результата

Код:

static List<LinkedList<String>> filterSublist(LinkedList<LinkedList<String>> l) { 
    return l.stream() 
     .filter(x -> l.stream().noneMatch(elem -> !elem.equals(x) && Collections.indexOfSubList(elem, x) != -1)) 
     .distinct() 
     .collect(Collectors.toList()); 
} 
+0

«Больше памяти эффективнее, так как оно не дублирует исходный список» - я понял, что это требование - вернуть отдельный список.Другие могут быть легко устранены. – dev8080

+0

@ dev8080 Требование по-прежнему выполняется, возвращается список. Но это решение не копирует полный первоначальный список, это пункт. Поэтому в случае, если имеется много подписок, которые удалены, использование памяти ниже. –

Смежные вопросы