简体   繁体   English

根据String Array中的单词过滤List

[英]Filter a List based on words from String Array

I have a result set having List<Employees> sent by another application. 我有一个结果集,其中包含由其他应用程序发送的List<Employees>

class Employee{
    Long id;
    String name;
    String gender;
    List<String> projects;
    // Getters
    // Setters
}

I need to write a method or lambda expression to filter the List using a bunch of query words ( String[] ) passed from the UI. 我需要编写一个方法或lambda表达式来使用从UI传递的一堆查询字( String[] )来过滤List

Any word in the String[] can match any variable (id, name, gender, projects). String[]中的任何单词都可以匹配任何变量(id,name,gender,projects)。 All List which have a match should be returned. 应返回所有匹配的列表。 part of name should also match eg: "john" should match List 1 and 3 in the example. 名称的一部分也应该匹配,例如:“john”应匹配示例中的列表1和3。

List<Employee> filter (empList, queryWords) {
    // code
}

Can you point me in the right direction to achive this? 你能指出我正确的方向来实现这一目标吗?

example:

List:
1.  121, john doe   , male  , (proj1)
2.  125, sam    , female, (proj4 proj5 proj9)
3.  129, john lam   , male  , (proj1 proj2 proj5)
4.  143, peter pan  , male  , (proj4 proj8) 
5.  151, linda  , female, (proj8 proj7 proj3 proj11)


Search Query Words:

1.  "female" "proj3"- should return only No.5
2.      "proj5"     - should return only No.2 and 3
3.      "john"          - should return No.1 and 3
4.      "pan"           - should return No.4

Write a method 写一个方法

private boolean employeeMatchesWord(Employee employee, String word)

that returns true if at least one field of the employee matches the given word. 如果员工的至少一个字段与给定的单词匹配,则返回true。

Then use 然后用

return empList.stream()
              .filter(employee -> Arrays.stream(queryWords)
                                        .anyMatch(word -> employeeMatchesWord(employee, word))
              .collect(Collectors.toList());
public List<Employee> filter(empList, queryWords){
    List<Employee> result = new ArrayList<Employee>();

    // look at each employee in the list
    for(Employee employee : empList){

        // look at each query string
        for(String queryWord : queryWords){

        // if any of the employee fields matches the query word, 
        // add it to our list and move to next employee
        if(employee.name.equals(queryWord) ||
            employee.gender.equals(queryWord) ||
            employee.id.toString().equals(queryWord) ||
            isQueryInList(queryWord, employee.projects)) {
                // add it to your results
                result.add(employee);

                // quit looking at the rest of the queryWords, 
                // we found one, thats enough, move on to the next employee
                break; 
            }
        }
    }

    return result;
}

private boolean IsQueryInList(String queryWord, List<String> items){
    //check each item in the list to see if it matches the queryWord
    for(String item : items){
        if(queryWord.equals(item)) {
            return true;
        }
    }

    //if we didn't find any item that matches, return false
    return false;
}

You could convert the query words array to a Set , create a Set of properties from all the employee's members, and use retainAll to determine which employees have at least one of the query words: 您可以将查询字数组转换为Set ,从所有员工的成员创建一Set属性,并使用retainAll确定哪些员工至少有一个查询字:

public static List<Employee> filter (List<Employee> empList, String[] queryWords) {
    Set<String> queryWordsSet = new HashSet<>(Arrays.asList(queryWords));

    return empList.stream().filter(e -> {
        Set<String> properties = new HashSet<>(e.getProjects());
        properties.addAll
            (Arrays.asList(e.getId().toString(), e.getName(), e.getGender()));
        properties.retainAll(queryWordsSet);
        return !properties.isEmpty();
    }).collect(Collectors.toList());
}

EDIT: 编辑:
As JB Nizet commented, the retainAll can be elegantly replaced with an anyMatch expression: 正如JB Nizet评论的那样, retainAll可以用anyMatch表达式优雅地替换:

public static List<Employee> filter (List<Employee> empList, String[] queryWords) {
    Set<String> queryWordsSet = new HashSet<>(Arrays.asList(queryWords));

    return empList.stream().filter(e -> {
        Set<String> properties = new HashSet<>(e.getProjects());
        properties.addAll
            (Arrays.asList(e.getId().toString(), e.getName(), e.getGender()));
        return properties.stream().anyMatch(queryWordsSet::contains);
    }).collect(Collectors.toList());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM