简体   繁体   English

如何将列表列表中的每个列表的前 N ​​个元素移动到列表的末尾

[英]How to move first N elements to the end of the list for each list in the list of lists

Is there any way in Prolog how can I move first N elements from a list and put them at the end.在 Prolog 中有什么方法可以从列表中移动前 N 个元素并将它们放在最后。 I wanna do this for each list in the list of lists.我想为列表列表中的每个列表执行此操作。 Example:例子:

Input:输入:

move(3, [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1,2,3], [3, 4, 5, 6, 7, 8, 9, 10, 11, 12]], R)

Result:结果:

R = [[4, 5, 6, 7, 8, 9, 1, 2, 3], [1,2,3], [6, 7, 8, 9, 10, 11, 12, 3, 4, 5]]

I have no idea, does anyone know how to do that?我不知道,有人知道怎么做吗?

If you execute the following query, Left and Right will be bound to two lists that, when concatenated together, result in [1,2,3,4,5] :如果您执行以下查询, LeftRight将绑定到两个列表,当连接在一起时,结果为[1,2,3,4,5]

?- append(Left, Right, [1,2,3,4,5]).

The above query admits 6 solutions ( Left being empty, the list [1] , the list [1,2] , etc.).上面的查询允许 6 个解决方案( Left为空、列表[1] 、列表[1,2]等)。 You can constrain the query by saying that Left exactly has three elements:您可以通过说Left恰好包含三个元素来限制查询:

?- length(Left, 3), append(Left, Right, [1,2,3,4,5]).
Left = [1, 2, 3]
Right = [4, 5]

This has only one solution.这只有一种解决方案。

The rotation consists in producing a list where the Left part is on the right of the Right list:旋转包括生成一个列表,其中Left部分位于Right列表的Right

?- length(Left, 3), 
   append(Left, Right, [1,2,3,4,5]),
   append(Right, Left, Result).
Left = [1, 2, 3]
Right = [4, 5]
Result = [4, 5, 1, 2, 3]

The first predicate you need to write is thus:因此,您需要编写的第一个谓词是:

rotate_left(List, Offset, Rotated) :-
  length(Left, Offset),
  append(Left, Right, List),
  append(Right, Left, Rotated).

Then you can apply this predicate on a list of lists.然后,您可以将此谓词应用于列表列表。


NB.注意。 you may consider using this version instead:你可以考虑使用这个版本:

rotate_left(List, Offset, Rotated) :-
    append(Left, Right, List),
    length(Left, Offset),
    append(Right, Left, Rotated).

It is a bit better because it allows Offset to be variable:它好一点,因为它允许Offset是可变的:

[eclipse 2]: rotate_left([a, b, c, d], N, [c, d, a, b]).

N = 2
Yes (0.00s cpu, solution 1, maybe more) ? ;

No (0.00s cpu)

With the original version, length(Left, N) has both its arguments variable, and it keeps producing answers with longer and longer lists.在原始版本中, length(Left, N)两个参数都是可变的,并且它会不断生成越来越长列表的答案。

You are doing the same operation on each element of the list-of-lists above, ie, take first three elements and append them at the back.您正在对上面列表列表的每个元素执行相同的操作,即,取前三个元素并将它们附加到后面。 So if you can define the operation itself first then it will be easy to do it for a list of lists.因此,如果您可以先定义操作本身,那么对列表列表进行操作就很容易了。

% If the predicate op/3 is already defined the you can easily define
% another one for a list the elements
op_for_lists([], _, []).
op_for_lists([X|Xs], N, [Y|Ys]) :-
    operation(X, N, Y), op_for_lists(Xs, N, Ys).

So if you take @coredump's answer and replace operation with rotate_left it will work.因此,如果您采用rotate_left的答案并将operation替换为rotate_left ,它将起作用。

You can also use maplist/3 with lambdas from yall library as follows您还可以将maplist/3yall库中的 lambdas 一起使用,如下所示

op_for_lists(Xs, N, Ys) :-
  maplist({N}/[In, Out]>>operation(In, N, Out), Xs, Ys).

It is easier if the constant argument is at the start, then you can simply use如果常量参数在开头更容易,那么你可以简单地使用

maplist(operation(N), Xs, Ys)

to get the result for list-of-lists获取列表列表的结果

Here's my approach:这是我的方法:

First: Extract the number of starting elements.第一:提取起始元素的数量。 Here M will work as a counter that will tell us when to stop when extracting the starting element.这里 M 将用作一个计数器,它会告诉我们在提取起始元素时何时停止。 The 0 in the base case is the indication to stop.基本情况中的 0 是停止的指示。

 s3(0,Rest,[], Rest):-!.
s3(M,[H|T],[H|R], Rest):-
    M1 is M-1,
    s3(M1,T,R, Rest).

Second: We need to append Rest (J) [which contains the remaining elements of the list] and R (Q) [which contains the starting elements].第二:我们需要附加 Rest (J) [包含列表的剩余元素] 和 R (Q) [包含起始元素]。

append(J,Q,L)

Third: Putting the code altogether.第三:把代码完全放在一起。

s3(0,Rest,[], Rest):-!.
s3(M,[H|T],[H|R], Rest):-
    M1 is M-1,
    s3(M1,T,R, Rest).

q1(M,[H|T],L):-
    s3(M,[H|T],Q,J),
    append(J,Q,L).

Example:例子:

?-q1(3,[3,4,5,6,7,8,9,10,11,12],L).
L = [6, 7, 8, 9, 10, 11, 12, 3, 4, 5]

?-q1(3,[1,2,3,4,5],L).
L = [4, 5, 1, 2, 3]

Now you can from this point on write a predicate that can deal with each list separately and give you the solution.现在您可以从现在开始编写一个谓词,该谓词可以分别处理每个列表并为您提供解决方案。

Another option is to use partition/4 (in SWI Prolog):另一种选择是使用 partition/4(在 SWI Prolog 中):

test(O):-
    L = [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1,2,3], [3, 4, 5, 6, 7, 8, 9, 10, 11, 12]],
    maplist(move(3),L,O).

greater(N,L,E):-
    nth1(I,L,E),I > N.

move(N,L,O):-
    partition(greater(N,L),L,LO,LP),
    append(LO,LP,O).

?- test(O).
O = [[4, 5, 6, 7, 8, 9, 1, 2, 3], [1, 2, 3], [6, 7, 8, 9, 10, 11, 12, 3, 4, 5]]

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

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