计算列表中有多少个元素满足谓词

时间:2020-09-16 18:49:51

标签: list prolog

给出一个整数列表的列表,例如[[3,10],[3,10,2],[5],[5,2],[5,3],[5,3,2],[5,3,10]],我想遍历每个子列表,并计算其中的总数为15。在这种情况下,对于子列表[3,10,2],该值为1。

我知道谓词aggregate_all/3,但是我在编写谓词以检查列表的每个元素时遇到了麻烦,我现在所拥有的类似于

fifteens([X|Xs]) :-
    sum_list(X, 15),
    fifteens(Xs).

在另一个谓词中,我有:

aggregate_all(count, fifteens(Combinations), Value).

其中Combinations是所讨论的整数列表的列表。

我知道我的fifteens谓词是有缺陷的,因为它说嵌套列表的 all 个元素必须总和为15,但是要解决这个问题,我如何取出{{ 1}}并逐一检查?我什至需要吗?谢谢。

2 个答案:

答案 0 :(得分:2)

首先,您的fifteens/2谓词没有,因为空列表,因此它将始终失败,因为由于递归,最终fifteens([])将被调用并失败。

此外,您还需要完全更改15个的定义,即使添加基本大小写,目前也要检查 ALL 元素-子列表以查看它们的总和是否为15。看如何将其与聚合一起使用。

要使用aggregate/3,您需要用fifteens/2表示,例如:对于我的组合列表的每个部分,分别检查每个子列表,即每个成员:

ifteens(L) :-
    member(X,L),
    sum_list(X, 15).

现在尝试:

?- aggregate_all(count, ifteens([[3,10],[3,10,2],[5],[5,2],[5,3],[5,3,2],[5,3,10]]), Value).

Value = 1.

答案 1 :(得分:1)

这是... foldl/4的工作。逻辑编程语言中的函数式编程习惯用法?是的,我们可以!

首先,对列表的可加值求和:

public List<RemoteUsersDTO> getAllRemoteUsers() {
    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();

    String OKTA_URL = "https:bmg.okta-emea.com/api/v1/users?limit=200";

    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.add("Authorization", "SSWS " + OKTA_API_KEY);
    HttpEntity<String> request = new HttpEntity<>(headers);
    String url = OKTA_URL;
    List<RemoteUsersDTO> remoteUserList = new ArrayList<>();
    while (url != null) {
        ResponseEntity<RemoteUsersDTO[]> response = restTemplate.exchange(
                url, HttpMethod.GET, request, RemoteUsersDTO[].class);
        RemoteUsersDTO[] remoteUsers = response.getBody();
        HttpHeaders responseHeaders = response.getHeaders();
        List<String> links = responseHeaders.get("Link");
        if (links != null) {
            for (String link : links) {
                if (link.contains("next")) {
                    String urlNext = StringUtils.substringBefore(link, ";");
                    urlNext = urlNext.substring(1, urlNext.length() - 1);
                    url = urlNext;
                } else {
                    url = null;
                }
            }
        } else {
            url = null;
        }
        if (remoteUsers != null && remoteUsers.length > 0) {
            remoteUserList.addAll(Arrays.asList(remoteUsers));
            log.info("Total remote users from okta: " + remoteUserList.size());
        } else {
            url = null;
        }
    }
    return remoteUserList;
}

然后,计算总和为15的那些:

sum_them(List,Sum) :-
   foldl(sum_goal,List,0,Sum).

sum_goal(Element,FromLeft,ToRight) :- 
   must_be(number,Element),
   must_be(number,FromLeft),
   ToRight is Element+FromLeft.

可以吗?让我们编写一些单元测试:

count_them(List,Count) :-
   foldl(count_goal,List,0,Count).

count_goal(Element,FromLeft,ToRight) :- 
   must_be(list(number),Element),
   must_be(number,FromLeft),
   sum_them(Element,15) -> succ(FromLeft,ToRight) ; FromLeft = ToRight.

等等:

:- begin_tests(fifteen_with_foldl).

test("first test",true(R==1)) :-
   count_them([[3,10],[3,10,2],[5],[5,2],[5,3],[5,3,2],[5,3,10]],R).

test("test on empty",true(R==0)) :-
   count_them([],R).

test("test with 2 hist",true(R==2)) :-
   count_them([[15],[],[1,1,1,1,1,10]],R).

:- end_tests(fifteen_with_foldl).