2013-05-16 51 views
5

Làm thế nào để đọc một dòng như một phạm vi trong D?Làm thế nào để đọc một chuỗi ký tự theo ký tự dưới dạng một phạm vi trong D?

Tôi biết có phạm vi trong D, nhưng tôi chỉ tự hỏi làm thế nào để chỉ đơn giản là lặp qua từng ký tự của một chuỗi bằng cách sử dụng khái niệm này?

Để hiển thị những gì tôi là sau đó, các mã tương tự tại Gò là:

for _, someChar := range someString { 
    // Do something 
} 
+1

http://ddili.org/ders/d.en/ranges.html – sigod

+0

@sigod, yea, nên đã kiểm tra sách của Ali! Nó chắc chắn là đi đến tài nguyên để đọc lên trên D công cụ ngay bây giờ. –

Trả lời

12

Điều đó phụ thuộc vào việc bạn muốn lặp qua các đơn vị mã hoặc điểm mã. Ngôn ngữ tự lặp trên mảng bởi các phần tử mảng, và chuỗi là mảng của các đơn vị mã, vì vậy nếu bạn chỉ cần sử dụng foreach với kiểu suy luận, sau đó với

foreach(c; "La Verité") 
    writeln(c); 

hai ký tự cuối cùng in sẽ vô nghia, vì é là một điểm mã gồm hai đơn vị mã UTF-8 và bạn đang in ra các đơn vị mã riêng lẻ (vì char là đơn vị mã UTF-8). Trong khi đó, nếu bạn thực hiện

foreach(dchar c; "La Verité") 
    writeln(c); 

thì thời gian chạy sẽ giải mã đơn vị mã thành điểm mã và é sẽ được in làm ký tự cuối cùng. Nhưng không cái nào trong số này thực sự hoạt động trên các chuỗi như các phạm vi. foreach hoạt động trên mảng nguyên bản mà không phải sử dụng API phạm vi đầu vào. Tuy nhiên, đối với tất cả các loại chuỗi, API phạm vi trông giống như

@property bool empty(); 
@property dchar front(); 
void popFront(); 

Nó hoạt động trên dây như dãy dchar-không loại đơn vị mã của họ. Điều này tránh các vấn đề với các chức năng như std.algorithm.filter hoạt động trên các đơn vị mã riêng lẻ, vì điều đó sẽ không có ý nghĩa. Hoạt động trên các điểm mã không phải là chính xác 100%, vì Unicode rất phức tạp liên quan đến việc kết hợp các điểm mã và đồ thị và điều gì đó, nhưng hoạt động trên các điểm mã gần đến mức chính xác hơn (và tôi tin rằng hỗ trợ cho graphemes vào thư viện chuẩn cho các trường hợp mà bạn cần và sẵn sàng trả hit hiệu suất). Vì vậy, có API phạm vi cho chuỗi hoạt động trên chúng như dãy dchar là xa chính xác hơn, và nếu bạn đã làm điều gì đó như

foreach(c; filter!"true"("La Verité")) 
    writeln(c); 

bạn sẽ iterating qua dchar, và é sẽ in một cách chính xác.Nhược điểm của tất cả điều này là thực tế là foreach trên chuỗi hoạt động theo cấp độ đơn vị mã theo mặc định trong khi API phạm vi cho chuỗi hoạt động trên chúng dưới dạng điểm mã, vì vậy bạn phải cẩn thận khi trộn các hoạt động mảng và dựa trên phạm vi hoạt động trên chuỗi. Đó cũng là lý do tại sao stringwstring không được coi là phạm vi truy cập ngẫu nhiên - chỉ là phạm vi hai chiều. Bạn không thể truy cập ngẫu nhiên trong O (1) trên các điểm mã khi chúng được tạo thành từ số lượng đơn vị mã khác nhau (trong khi dstring phạm vi truy cập ngẫu nhiên, bởi vì với UTF-32, mọi đơn vị mã là điểm mã).

+0

Điều gì sẽ xảy ra nếu tôi nhập std.array cung cấp các hàm Phạm vi cần thiết trên cấp UFCS, sẽ lặp lại qua một chuỗi vẫn giống nhau không? – dav1d

+0

@ dav1d 'foreach' trên mảng sẽ chỉ sử dụng API mảng. Đối với mảng, các hàm dựa trên dải ô phải được sử dụng một cách rõ ràng. Và thực sự, gây phiền toái vì sự mâu thuẫn với foreach là, làm cho hành vi của nó phụ thuộc vào việc std.array được nhập hay không sẽ rất dễ bị lỗi, vì việc thêm hoặc loại bỏ việc nhập đó có thể thay đổi đáng kể hành vi mã của bạn tùy thuộc vào nó đang làm. –

+0

Vâng, tôi đã thực sự hy vọng nó sẽ không thay đổi mã. Nhưng mặt khác, UFCS cho phép lặp qua các đối tượng không thực hiện giao diện opApply (có thể sai ở đây) hoặc phạm vi. Cảm ơn bạn đã làm rõ. – dav1d

1
foreach(ch; str) 
    do_something(ch); 

Một chuỗi là một InputRange. An InputRange thực hiện ba điều:

  • trống; nó có trống không?
  • trước; cho tôi món đồ tiếp theo.
  • popFront; trước phạm vi, nếu không mặt trước sẽ trả về tương tự.

foreach "hiểu" cách hoạt động với dải ô, do đó, nó "hoạt động".

Nhưng tôi không nói Go, vì vậy tôi không hoàn toàn chắc chắn rằng chúng tôi đang nói cùng một ngôn ngữ.

+0

Vâng, tất nhiên, Ugh, không biết làm thế nào tôi có thể quên điều này, đã sử dụng nó một vài lần rồi, vì vậy tôi nên biết ... gotta đổ lỗi cho việc thiếu ngủ đêm qua :) –

+0

Tôi nghe bạn, Tôi không hoàn toàn sáng suốt vào lúc này. – 0b1100110

+2

Coi chừng suy luận kiểu ở đây. Mã đó đang lặp qua các đơn vị mã, không phải là các điểm mã, vì vậy nó không hoạt động đúng trên Unicode. –

Các vấn đề liên quan