Фильтрация коллекции с коллекцией предикатов и соответствие порогу - PullRequest
0 голосов
/ 12 октября 2018

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

Я знаю, как сделать это без порога, и вот мое решение:

List<String> filter(List<Predicate<String>> predicateList, List<String> stringList) {
    return stringList.stream()
                     .filter(predicateList.stream()
                                          .reduce(x -> !(x.isEmpty()), Predicate::and))
                     .collect(Collectors.toList());
}

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

List<String> filtrr(List<Predicate<String>> predicateList, List<String> stringList, Double threshold) {}

РЕДАКТИРОВАТЬ: Например, метод должен пройти модульный тест следующим образом:

@Test
void filtrrTest() {
    Double threshold = 0.65;

    Predicate<String> predicate = p -> p.contains("lorem");
    Predicate<String> predicate1 = p -> p.length() > 10;
    Predicate<String> predicate2 = p -> p.contains("sed");

    List<Predicate<String>> predicateList = Arrays.asList(predicate, predicate1, predicate2);

    String string = "lorem ipsum dolor sit amet sed";
    String string1 = "consectetur adipiscing elit, sed do eiusmod";
    String string2 = "ipsum";
    String string3 = "adipiscing elit";
    String string4 = "sed do eiusmod";

    List<String> stringList = Arrays.asList(string, string1, string2, string3, string4);
    List<String> expectedList = Arrays.asList(string, string1, string4);

    assertEquals(expectedList, ClassName.filtrr(predicateList, stringList, threshold));
}

1 Ответ

0 голосов
/ 12 октября 2018

Я бы сначала создал универсальный служебный метод, который проверяет, соответствует ли данный элемент до threshold % предикатов:

public static <T> boolean matchingSome(
        T elem, 
        List<Predicate<T>> predicates, 
        double threshold) {

    long predsToMatch = (long) ((double) predicates.size() * threshold);

    long predsMatched = predicates.stream()
        .filter(p -> p.test(elem))
        .limit(predsToMatch) // this limit is to short-circuit as soon as
        .count();            // predsToMatch predicates evaluate to true

    return predsMatched == predsToMatch;
}

Обратите внимание, что я закорачиваю поток, как только predsToMatch предикатов оценили как true.Это сделано для того, чтобы избежать дальнейшей оценки дальнейших предикатов.

Теперь просто соберите все строки, для которых приведенный выше метод возвращает true:

List<String> result = stringList.stream()
    .filter(s -> matchingSome(s, predicateList, threshold))
    .collect(Collectors.toList());
...