【问题标题】:How do I find the longest list in a list of lists?如何在列表列表中找到最长的列表?
【发布时间】:2009-11-02 09:10:11
【问题描述】:

我有一个列表,我需要找到其中最长的一个。如果有多个长度相同,则返回的相同。谢谢。

【问题讨论】:

  • 你能写一个 3 位谓词来比较两个列表并“返回”较长的那个吗?
  • 嗯,也许吧。稍后我会看的。现在开始讲课。

标签: list prolog


【解决方案1】:

这是一个通用谓词,它扫描列表以查找由给定目标定义的单个成员。

select_element(Goal, [Head | Tail], Selected) :-
    select_element(Goal, Tail, Head, Selected).


select_element(_Goal, [], Selected, Selected).

select_element(Goal, [Head | Tail], Current, FinalSelected) :-
    call(Goal, Head, Current, Selected),
    select_element(Goal, Tail, Selected, FinalSelected).

假设你定义了一个谓词

get_bigger_number(N1, N2, N) :-
    N is max(N1, N2).

现在你可以执行了:

?- select_element(get_bigger_number, [5, 1, -2, 10, 3.2, 0], Selected).

Selected = 10

所以你现在需要做的就是定义一个谓词get_longer_list(L1, L2, L), 并使用它来代替get_bigger_number/3

当然,使用像select_element/3 这样的通用谓词可能效率不高。例如,您应该尽量避免多次计算同一个列表的长度,因为这种计算在 Prolog 中很慢(至少如果在 Prolog 中以标准方式实现)。

【讨论】:

  • 我不确定如果数字是实际列表会怎样。因为列表的头部将是一个列表。
  • select_element/3 不关心列表元素的性质(例如原子或列表)。一切都取决于您必须编写的谓词 (get_longer_list/3)。
【解决方案2】:

请考虑我的方法。

longest([L], L) :-
   !.
longest([H|T], H) :- 
   length(H, N),
   longest(T, X),
   length(X, M),
   N > M,
   !.
longest([H|T], X) :-
   longest(T, X),
   !.

那你可以参考一下:

?- longest([[1]], N).
N = [1] ;

?- longest([[1],[2]], N).
N = [2] .

?- longest([[1],[2], [3,3,3], [2]], N).
N = [3, 3, 3] ;

?- longest([[1],[2], [3,3,3], [2]], N).
N = [3, 3, 3].

?- longest([[1],[2], [3,3,3], [2], [4,4,4,4]], N).
N = [4, 4, 4, 4] .

?- longest([[1],[2], [3,3,3], [2], [4,4,4,4]], N).
N = [4, 4, 4, 4] ;

你好!

【讨论】:

  • 当然,你也可以验证被操作的对象实际上是列表。
  • 解决方案的复杂度为 O(n^2)。对于这样一个简单的问题来说,这太过分了......
  • 目标longest([[1],[2]],[1]) 失败。它应该成功!
【解决方案3】:

我们根据 定义longest/2 max_of_by/3length/2 一起使用:

longest(Xss,Ys) :-
   max_of_by(Ys,Xss,length).

示例查询:

?- longest([[1],[2]],Xs).      % we expect   multiple solutions
  Xs = [1]                
; Xs = [2].                    % we    _get_ multiple solutions

?- longest([[2,1,3],[7,5],[1,8,2,3,1],[2,7,1,4]],Xs).
Xs = [1,8,2,3,1].              % succeeds deterministically

【讨论】:

    【解决方案4】:

    这是另一种有效且易于理解的方法。思路是找出列表中所有列表的长度,使用max_list得到最长列表的长度,然后找到一个那么长的列表。这样做的好处是它将返回所有最长长度的列表。

    lengths([],[]).
    lengths([H|T], [LH|LengthsT]) :-
        length(H, LH),
        lengths(T, LengthsT).
    
    lengthLongest(ListOfLists, Max) :-
        lengths(ListOfLists, Lengths),
        max_list(Lengths, Max).
    
    longestList(ListOfLists, Longest) :-
        lengthLongest(ListOfLists, Len),
        member(Longest, ListOfLists),
        length(Longest, Len).
    

    【讨论】:

    • s(X) 用于返回 所有 个最大长度的列表。
    【解决方案5】:
    
    % Correct again.
    
    longest(LL,LX) :-
            findmax(Len,(append(_,[L|_],LL),length(L,Len)),MaxLen),
            append(_,[LX|_],LL),
            length(LX,MaxLen).
    
    findmax(V,P,Max) :-
            findall(V,P,L),
            max(L,Max).
    
    max([N],N) :- !.
    max([N|R],Max) :-
            max(R,Max2),
            max3(N,Max2,Max).
    
    max3(N,Max2,N) :- N > Max2,!.
    max3(N,Max2,Max2).
    

    【讨论】:

      【解决方案6】:

      要获得最长列表的长度:

      %sample: longest([[2,1,3],[7,5],[1,8,2,3,1],[2,7,1,4]],L,LEN).
      
      longest([L], L, _) :-
         !.
      longest([H|T], H, _) :-
         length(H, N),
         longest(T, X, N),
         length(X, M),
         N > M,
         !.
      longest([_|T], X, LEN) :-
         length(X, LEN),
         longest(T, X, LEN),
         !.
      

      【讨论】:

        猜你喜欢
        • 2020-07-17
        • 2022-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-12
        相关资源
        最近更新 更多