Nhiều thuật toán (như thuật toán để tìm hoán vị tiếp theo của danh sách theo thứ tự từ điển) liên quan đến việc tìm chỉ mục của phần tử cuối cùng trong danh sách. Tuy nhiên, tôi đã không thể tìm ra cách để làm điều này trong Mathematica mà không phải là vụng về. Cách tiếp cận đơn giản nhất sử dụng LengthWhile
, nhưng có nghĩa là đảo ngược toàn bộ danh sách, có khả năng không hiệu quả trong trường hợp bạn biết phần tử bạn muốn ở gần cuối danh sách và đảo ngược ý nghĩa của vị từ:Tìm kiếm từ cuối danh sách trong Mathematica
findLastLengthWhile[list_, predicate_] :=
([email protected] - LengthWhile[[email protected], ! [email protected]# &]) /. (0 -> $Failed)
Chúng tôi có thể thực hiện một vòng lặp rõ ràng, bắt buộc với Do
, nhưng điều đó cũng sẽ trở nên hơi khó khăn. Nó sẽ giúp đỡ nếu Return
thực sự sẽ trở về từ một hàm thay vì Do
khối, nhưng nó không, vì vậy bạn cũng có thể sử dụng Break
:
findLastDo[list_, pred_] :=
Module[{k, result = $Failed},
Do[
If[[email protected][[k]], result = k; Break[]],
{k, [email protected], 1, -1}];
result]
Cuối cùng, tôi quyết định lặp lại sử dụng đuôi-đệ quy, mà có nghĩa là chấm dứt sớm sẽ dễ dàng hơn một chút. Sử dụng lạ nhưng hữu ích #0
ký hiệu cho phép chức năng ẩn danh tự gọi mình, điều này trở thành:
findLastRecursive[list_, pred_] :=
With[{
step =
Which[
#1 == 0, $Failed,
[email protected][[#1]], #1,
True, #0[#1 - 1]] &},
step[[email protected]]]
Tất cả điều này dường như quá khó khăn, mặc dù. Có ai nhìn thấy một cách tốt hơn?
EDIT để thêm: Tất nhiên, giải pháp ưa thích của tôi có lỗi có nghĩa là nó bị hỏng trong danh sách dài vì $IterationLimit
.
In[107]:= findLastRecursive[Range[10000], # > 10000 &]
$IterationLimit::itlim: Iteration limit of 4096 exceeded.
Out[107]= (* gack omitted *)
Bạn có thể sửa lỗi này với Block
:
findLastRecursive[list_, pred_] :=
Block[{$IterationLimit = Infinity},
With[{
step =
Which[
#1 == 0, $Failed,
[email protected][[#1]], #1,
True, #0[#1 - 1]] &},
step[[email protected]]]]
$IterationLimit
không phải là tính năng Mathematica yêu thích của tôi.
Nếu chỉ các danh sách được thể hiện dưới dạng cấu trúc được liên kết kép ... –
bạn có chắc là dòng mã đầu tiên của bạn là chính xác không? Trừ khi tôi không hiểu những gì nó là nghĩa vụ phải làm không nên thứ hai 'LengthWhile' được' LengthWhile [danh sách // Reverse, predicate @ # &] '? Vì vậy, thêm một 'đảo ngược' và loại bỏ'! '? –
@Sjoerd C. de Vries Vâng, bạn nói đúng. Tôi đã chỉnh sửa trong bản sửa lỗi. – Pillsy