2013-08-28 29 views
6

Tôi đang cố gắng thực hiện thao tác cấu trúc dữ liệu lồng nhau có chứa danh sách các phần tử. Sau khi mucking xung quanh với các cách tiếp cận khác nhau cuối cùng tôi đã giải quyết trên ống kính như là cách tốt nhất để đi về việc này. Chúng hoạt động hoàn hảo cho việc tìm kiếm và sửa đổi các phần tử cụ thể của cấu trúc, nhưng cho đến nay tôi đã nói về cách thêm các phần tử mới. Từ những gì tôi đã đọc, tôi không thể sử dụng kỹ thuật Traversal vì nó vi phạm luật Traversal để chèn phần tử mới vào danh sách và giả sử tôi thậm chí có thể tìm ra cách thực hiện điều đó bằng cách sử dụng Traversal in nơi đầu tiên (tôi vẫn còn khá yếu với Haskell, và các chữ ký kiểu cho hầu hết mọi thứ trong gói thấu kính làm cho đầu tôi quay).Chèn vào danh sách tại một vị trí cụ thể bằng cách sử dụng ống kính

Cụ thể những gì tôi đang cố gắng thực hiện là tìm một số phần tử trong danh sách các phần tử khớp với công cụ chọn cụ thể, sau đó chèn phần tử mới trước hoặc sau phần tử được so khớp (đối số khác nhau cho hàm trước hoặc sau trận đấu). Control.Lens đã có một cái gì đó có thể thực hiện những gì tôi đang cố gắng để làm và sự hiểu biết của tôi về các chữ ký loại chỉ là quá yếu để xem nó? Có cách nào tốt hơn để hoàn thành những gì tôi đang cố gắng làm không?

Nó sẽ khá tầm thường nếu tôi chỉ cố thêm một phần tử mới vào đầu hoặc cuối danh sách, nhưng chèn nó ở đâu đó cụ thể ở giữa là phần khó. Trong một số mã trước ống kính tôi viết, tôi đã sử dụng một lần để hoàn thành những gì tôi muốn, nhưng nó bắt đầu nhận được gnarly trên các phần lồng nhau sâu hơn của cấu trúc (EG gấp trong một lần trong một lần) Tôi quay sang Control.Lens để cố gắng gỡ rối một số mớ hỗn độn đó.

+1

Bạn có cân nhắc điều gì đó giống như một người theo thuyết ziplist thay vì danh sách bình thường không? Điều đó sẽ giúp bạn dễ dàng chèn phần tử vào trước hoặc sau phần tử lấy nét của bạn. – kqr

+0

Tôi đã xem xét nó, nhưng cách cấu trúc dữ liệu ban đầu được xây dựng sẽ khó chuyển đổi thành ziplist vì vậy tôi có thể phải chuyển đổi nó sau khi thực tế có nghĩa là một hệ thống phân cấp kiểu hoàn toàn riêng biệt chỉ để chứa các ziplists. Đó là một trong hai điều đó hoặc tôi chuyển đổi từ danh sách thành ziplist và quay lại mỗi khi tôi cần chèn, mà tôi có thể làm, nhưng dường như không tốt hơn là chỉ cần gấp trên toàn bộ danh sách ngay từ đầu. – Orclev

Trả lời

2

Tôi nghĩ rằng một phương pháp đơn giản sẽ được phá vỡ các vấn đề trong:

  • Một chức năng mà là của [a] -> SomeAddtionalData -> [a], mà về cơ bản là trách nhiệm chuyển danh sách vào một danh sách khác sử dụng một số dữ liệu cụ thể. Đây là nơi bạn thêm/xóa các phần tử khỏi danh sách và lấy danh sách mới
  • Sử dụng lense để trích xuất Danh sách từ một số cấu trúc dữ liệu lồng nhau, chuyển danh sách đó đến hàm được xác định ở trên, đặt danh sách trả về trong cấu trúc dữ liệu lồng nhau bằng cách sử dụng lense .

Đoạn cuối cùng của bạn là dấu hiệu về những gì sẽ xảy ra khi bạn cố gắng làm quá nhiều bằng cách sử dụng sự trừu tượng chung chung như Lens. Các trừu tượng chung này là tốt cho một số mục đích chung và mọi thứ khác đều dành riêng cho vấn đề của bạn và nên được thiết kế xung quanh các hàm cũ (ít nhất là ban đầu, sau này trong dự án của bạn). loại lớp học vv).

+0

Tôi nghĩ bạn đã bỏ lỡ điều gì đó với đoạn cuối, đó là những gì đã xảy ra khi tôi không sử dụng ống kính. Bản chất lồng ghép của dữ liệu có nghĩa là tôi đã đi nhiều cấp độ danh sách bằng cách sử dụng các nếp gấp để tìm vị trí tôi muốn chèn phần tử mới tại. Sử dụng ống kính để đi bộ ít nhất các danh sách cha mẹ có vẻ sạch hơn, mặc dù hiện tại có vẻ như tôi có thể bị kẹt với ít nhất một lần để thực hiện chèn thực tế. – Orclev

2

Một số ý kiến ​​về vấn đề của bạn:

trả lời câu hỏi: Có thể có một cách để làm những gì bạn muốn làm. Thư viện của Lens thật tuyệt vời. Những gì không có là một cách đơn giản hoặc rõ ràng để làm cho nó xảy ra. Tôi nghĩ rằng nó sẽ liên quan đến partsOf combinator nhưng tôi không chắc chắn.

Nhận xét về ống kính: Thư viện ống kính thực sự tuyệt vời và có thể áp dụng cho một số lượng lớn sự cố. Sự cám dỗ ban đầu của tôi khi tôi học thư viện là cố gắng phù hợp với mọi thứ trong việc truy cập hoặc đột biến của Lens. Những gì tôi phát hiện ra là sử dụng thư viện ống kính tốt hơn để khai thác cấu trúc dữ liệu phức tạp, nhưng một khi tôi có một yếu tố đơn giản thì tốt hơn là sử dụng các kỹ thuật truyền thống hơn mà tôi đã biết. giới hạn.

Lời khuyên bạn không yêu cầu: Chèn phần tử vào giữa danh sách là một ý tưởng tồi. Không phải là nó không thể được thực hiện nhưng nó có thể kết thúc là một hoạt động O (n^2). (See also this StackOverflow answer.) Danh sách zip hoặc một số khác functional data structure có thể là một ý tưởng tốt hơn. Là một lợi ích phụ, một số cấu trúc này có thể được tạo ra từ lớp At cho phép chèn và xóa bằng cách sử dụng các bộ phối hợp ống kính một phần.

4

Sử dụng lens pacakge

Nếu chúng ta bắt đầu với biết chức năng id có thể được sử dụng như một ống kính:

import Control.Lens 
> [1,2,3,4] ^. id 
[1,2,3,4] 

Sau đó, chúng ta có thể chuyển sang cách danh sách có thể được chỉnh sửa:

> [1,2,3,4] & id %~ (99:) 
[99,1,2,3,4] 

trên đây cho phép chèn vào đầu danh sách. Để tập trung vào các phần sau của danh sách, chúng tôi có thể sử dụng _tail từ số Control.Lens.Cons module.

> [1,2,3,4] ^. _tail 
[2,3,4] 
> [1,2,3,4] & _tail %~ (99:) 
[1,99,2,3,4] 

Bây giờ để khái quát này cho vị trí thứ n

> :{ 
let 
_drop 0 = id 
_drop n = _tail . _drop (n - 1) 
:} 
> [1,2,3,4] ^. _drop 1 
[2,3,4] 
> [1,2,3,4] & _drop 0 %~ (99:) 
[99,1,2,3,4] 
> [1,2,3,4] & _drop 1 %~ (99:) 
[1,99,2,3,4] 

Một bước cuối cùng để khái quát này trên tất cả các loại với một Cons instance chúng ta có thể sử dụng cons hoặc <|.

> [1,2,3,4] & _drop 1 %~ (99<|) 
[1,99,2,3,4] 
> import Data.Text 
> :set -XOverloadedStrings 
> ("h there"::Text) & _drop 1 %~ ('i'<|) 
"hi there" 
Các vấn đề liên quan