【问题标题】:How to filter set of list based on another set of list?如何根据另一组列表过滤一组列表?
【发布时间】:2020-08-14 23:35:09
【问题描述】:

我有这个输入:

Set<List<String>> allSafe = new HashSet<>();
Set<List<String>> allErrors = new HashSet<>();

如何根据 allSafe 过滤 allErrors 的元素?例如,如果我有:

allErrors = [["h","k"],["hi","ho","ha"]]

allSafe = [["h","k"],["sh","ho","ii","oo"],["h","zzz"]]

那么预期的输出应该是:

filteredAllSafe = [["sh","ii","oo"],["zzz"]]

这是我的尝试,但没有按预期工作:它返回空列表集:

public static Set<List<String>> filterSafe(
        Set<List<String>> allSafe,
        Set<List<String>> allErrors) {

    Set<List<String>> filteredSet = allSafe.stream()
            .filter(s -> s.contains(allErrors))
            .collect(Collectors.toSet());

    return filteredSet;
}

【问题讨论】:

    标签: java list multidimensional-array set filtering


    【解决方案1】:

    按如下方式进行:

    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    public class Main {
        public static void main(String[] args) {
            Set<List<String>> allErrors = Set.of(
                    List.of("h", "k"),
                    List.of("hi", "ho", "ha"));
            Set<List<String>> allSafe = Set.of(
                    List.of("h", "k"),
                    List.of("sh", "ho", "ii", "oo"),
                    List.of("h", "zzz"));
            Set<List<String>> filteredSet = new HashSet<List<String>>();
            boolean found;
            List<String> list;
            for (List<String> safe : allSafe) {
                list = new ArrayList<String>();
                for (String strSafe : safe) {
                    found = false;
                    for (List<String> error : allErrors) {
                        for (String strError : error) {
                            if (strSafe.equals(strError)) {
                                found = true;
                                break;
                            }
                        }
                        if (found) {
                            break;
                        }
                    }
                    if (!found) {
                        list.add(strSafe);
                    }
                }
                if (!list.isEmpty()) {
                    filteredSet.add(list);
                }
            }
            System.out.println(filteredSet);
        }
    }
    

    输出:

    [[sh, ii, oo], [zzz]]
    

    【讨论】:

      【解决方案2】:

      这是一个使用流的解决方案,将所有错误合并到一个集合中以进行更简单的过滤

      Set<String> errorSet = allErrors.stream()
              .flatMap(List::stream)
              .collect(Collectors.toSet());
      
      Set<List<String>> filteredSet = new HashSet<>();
      allSafe.stream().forEach(l -> {
          List<String> filtered = l.stream()
                  .filter(e -> !errorSet.contains(e))
                  .collect(Collectors.toList());
          if (!filtered.isEmpty())
              filteredSet.add(filtered);
      });
      

      【讨论】:

        【解决方案3】:

        您可以先将 allErrors 展平为一组,然后从 allSafe 过滤每个列表,使其不包含任何错误:

        public static void main(String[] args) {
            Set<List<String>> allErrors = Set.of(
                    List.of("h", "k"),
                    List.of("hi", "ho", "ha"));
        
            Set<List<String>> allSafe = Set.of(
                    List.of("h", "k"),
                    List.of("sh", "ho", "ii", "oo"),
                    List.of("h", "zzz"));
        
            System.out.println(filterSafe(allSafe, allErrors));
            // [[sh, ii, oo], [zzz]]
        }
        
        public static Set<List<String>> filterSafe(
                Set<List<String>> allSafe,
                Set<List<String>> allErrors) {
            // flatten 'allErrors' into one set
            Set<String> flatErrors = allErrors.stream()
                    .flatMap(List::stream)
                    .collect(Collectors.toSet());
            // return resulting set
            return allSafe.stream()
                    .map(list -> list.stream()
                            // each list doesn't contain errors
                            .filter(e -> !flatErrors.contains(e))
                            // list without errors or
                            // empty list if all errors
                            .collect(Collectors.toList()))
                    // resulting set doesn't contain empty lists
                    .filter(list -> list.size() > 0)
                    // resulting set
                    .collect(Collectors.toSet());
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-10
          • 2019-01-17
          • 1970-01-01
          相关资源
          最近更新 更多