Tải bản đầy đủ (.docx) (8 trang)

Mảng kết hợp

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (83.19 KB, 8 trang )

Mảng kết hợp
Mảng kết hợp là gì?
Mảng kết hợp cũng tựa nh mảng (kiểu danh sách) mà ta đã thảo luận trớc đây,
trong đó nó là một tuyển tập các dữ liệu vô hớng, với các phần tử riêng đợc chọn ra
bằng một giá trị chỉ số nào đó. Không giống mảng danh sách, giá trị chỉ số của mảng
kết hợp không phải là số nguyên không âm nhỏ, mà thay vào đó là vô hớng tuỳ ý.
Những vô hớng này (còn gọi là khoá) đợc dùng về sau để tìm kiếm các giá trị từ
mảng này.
Các phần tử của mảng kết hợp không có thứ tự đặc biệt. Bạn hãy xem chúng tựa
nh bàn đầy những quân bài. Nửa trên của các con bài là khoá, còn nửa dới là giá trị
của chúng. Mỗi lần bạn đặt một giá trị vào trong mảng kết hợp thì một con bài mới
lại đợc tạo ra. Về sau khi bạn muốn sửa đổi giá trị này, bạn cho khoá, còn Perl tìm ra
đúng con bài. Cho nên, thực sự, trật tự của các con bài là không quan trọng. Trong
thực tế, Perl cất giữ các con bài (cặp khoá-giá trị) theo thứ tự bên trong đặc biệt để dễ
dàng tìm ra một con bài đặc biệt, cho nên Perl không phải duyệt qua tất cả các cặp để
tìm ra đúng con bài. Bạn không thể kiểm soát đợc trật tự này, cho nên đừng có thử.
Biến mảng kết hợp
Tên biến mảng kết hợp là dấu phần trăm (%) theo sau bởi một chữ, theo sau nữa
là không hay nhiều chữ, chữ số và dấu gạch thấp. Nói cách khác, phần đi sau dấu
phần trăm giống hệt cái mà chúng ta có cho tên biến vô hớng và biến mảng. Và giống
nh chẳng có quan hệ gì giữa $fred và @fred, biến mảng kết hợp %fred cũng chẳng
liên quan gì tới hai loại biến kia cả.
Thay vì tham khảo tới toàn bộ mảng kết hợp, thông dụng hơn cả là ta tạo ra một
mảng kết hợp và thâm nhập vào nó bằng cách tham khảo tới các phần tử của nó. Mỗi
phần tử của mảng đều là một vô hớng tách biệt, đợc thâm nhập tới bởi một chỉ mục
vô hớng, gọi là khoá. Các phần tử của mảng kết hợp %fred vậy đợc tham khảo đến
bằng $fred{$key} với $key là bất kì biểu thức vô hớng nào. Lại chú ý rằng việc thâm
nhập vào một phần tử của mảng không bắt đầu bằng cùng chỗ ngắt nh tên của toàn bộ
mảng.
Giống nh với mảng danh sách, bạn có thể tạo ra những phần tử mới bằng việc gán
cho mảng một phần tử:


$fred{aaa} = bbb ; # tạo ra khoá aaa, giá trị bbb
$fred{234.5} = 456.7; # tạo ra khoá 234.5, giá trị 456.7
Hai câu lệnh này tạo ra hai phần tử trong mảng. Những tham khảo về sau tới cùng
những phần tử này (dùng cùng khoá) sẽ cho lại giá trị đợc cất giữ.
print $fred{aaa}; # in bbb
$fred{234.5} += 3; # làm cho nó thành 459.7
Việc tham khảo tới một phần tử không có sẵn sẽ cho lại giá trị undef, giống nh với
mảng danh sách hay biến vô hớng không xác định.
Biểu diễn hằng kí hiệu cho mảng kết hợp
Bạn có thể muốn thâm nhập vào mảng kết hợp nh một toàn thể, để hoặ khởi đầu
nó hay sao chép nó sang mảng kết hợp khác. Perl không thực sự có biểu diễn hằng kí
hiệu cho mảng kết hợp, cho nên thay vì thế nó tháo rời mảng ra nh một danh sách.
Mỗi cặp phần tử trong danh sách (mà bao giờ cũng phải có một số chẵn phần tử) đều
xác định ra một khoá và giá trị tơng ứng của nó. Biểu diễn tháo rời này có thể đợc
gán vào trong mảng kết hợp khác, mà rồi sẽ tái tạo lại cùng mảng kết hợp đó. Nói
cách khác:
@fred_list = %fred;
# @fred_list nhận (aaa, bbb, 234.5, 456.7)
%barney = @fred_list; # tạo ra %barney giống %fred
%barney = %fred; # cách nhanh hơn để làm cùng việc đó
%smooth = (aaa, bbb, 234.5, 456.7);
# tạo ra %smooth giống nh %fred, từ các giá trị hằng kí hiệu
Trật tự của các cặp khoá-giá trị là tuỳ ý trong cách biểu diễn tháo rời này, và
không thể kiểm soát đợc. Cho dù bạn có tráo đổi một số giá trị và tạo ra một mảng
nh một toàn thể thì danh sách tháo rời thu đợc vẫn cứ theo bất kì trật tự nào mà Perl
đã tạo ra để thâm nhập hiệu quả vào các phần tử riêng. Bạn đừng bao giờ nên dựa trên
bất kì trật tự đặc biệt nào.
Các toán tử mảng kết hợp
Sau đây là một số toán tử cho mảng kết hợp.
Toán tử keys()

Toán tử keys(%tên mảng) cho lại danh sách các tất cả các khoá hiện có trong
mảng kết hợp %tên mảng . Nói cách khác, nó tựa nh các phần tử đợc đánh số lẻ (một,
ba năm vân vân) của danh sách đợc việc tháo rời %tên mảng cho lại trong ngữ cảnh
mảng, và trong thực tế, cho lại chúng theo trật tự đó. Nếu không có phần tử nào trong
mảng kết hợp thì keys() cho lại một danh sách rỗng.
Chẳng hạn, bằng việc dùng mảng kết hợp từ thí dụ trớc:
$fred{aaa} = bbb;
$fred{234.5} = 456.7;
@list = keys(%fred) ; # @list nhận đợc (aaa, 234.5) hay (234.5, aaa)
Các dấu ngoặc tròn là tuỳ chọn: keys %fred cũng giống nh keys(%fred).
foreach $key (key %fred) {# một lần cho mỗi khoá của %fred
print tại $key chúng ta có $fred{$key}\n; # in khoá và giá trị }
Thí dụ này cũng chỉ ra rằng các phần tử mảng kết hợp có thể chen lẫn nhau trong
các xâu nháy kép. Tuy nhiên bạn không thể xen lẫn toàn bộ mảng
*
.
Trong ngữ cảnh vô hớng, toán tử keys() cho lại số các phần tử (cặp khoá-giá trị)
trong mảng kết hợp. Chẳng hạn, bạn có thể tìm ra liệu mảng kết hợp có rỗng hay
không:
if (keys(%mảng nào đó)) { # nếu keys() khác không:
...; # mảng là khác rỗng
}
# ... hoặc ...
while (keys(%mảng nào đó) < 10) {
... ; # cứ lặp chu trình khi ta có ít hơn 10 phần tử
}
Toán tử values()
Toán tử values(%tên mảng) cho lại một danh sách tất cả các giá trị hiện tại của
%tên mảng, theo cùng trật tự nh các khoá đợc toán tử keys(%tên mảng) cho lại. Nh
với keys(), các dấu ngoặc tròn là tuỳ chọn. Chẳng hạn:

%lastname = (); # buộc %lastname là rỗng
$lastname(fred} = flintstore;
$lastname{barney} = rubble;
@lastname = values(%lastname); # lấy các giá trị
Tại điểm này @lastname chứa hoặc (flintstore, rubble) hay đảo ngợc của nó.
Toán tử each()
Nếu bạn muốn lặp trên (tức là xem xét mọi phần tử của) toàn bộ mảng kết hợp,
thì bạn có thể dùng keys(), duyệt xét từng khoá đợc cho lại và nhận giá trị tơng ứng.
Trong khi phơng pháp này thờng hay đợc dùng, một cách hiệu quả hơn là dùng
each(%tên mảng), toán tử sẽ cho lại cặp khoá-giá trị nh một danh sách hai phần tử.
Với mỗi lần thực hiện toán tử này cho cùng mảng, cặp khoá-giá trị kế tiếp sẽ đợc cho
lại, cho tới khi tất cả các phần tử đều đã đợc thâm nhập tới. Khi không còn cặp nào
nữa thì each() cho lạimột danh sách rỗng.
Vậy chẳng hạn, để bớc qua mảng %lastname trong thí dụ trớc, hãy làm điều gì đó
tựa nh thế này:
while (($first, $last) = each(%lastname)) {
print Tên cuối cùng của $first là $last\n;
}
*
*
Này, bạn có thể đấy, bằng cách dùng lát cắt, nhng chúng ta không nói về lát cắt ở đây.
Việc gán một giá trị mới cho toàn bộ mảng sẽ đặt lại từng toán tử each() cho từ
đầu. Việc bổ sung hay loại bỏ các phần tử của mảng thì rất có thể gây ra lẫn lộn
each() (và có thể gây lẫn lộn cho cả bạn nữa).
Toán tử delete
Cho đến giờ, với điều bạn biết đợc, bạn có thể thêm phần tử vào mảng kết hợp,
nhng bạn không thể loại bỏ chúng (một việc khác hơn là gán giá trị mới cho toàn bộ
mảng). Perl cung cấp toán tử delete để loại bỏ các phần tử. Toán hạng của delete là
một tham khảo mảng kết hợp, hệt nh nếu bạn chỉ nhìn vào một giá trị đặc biệt. Perl
loại bỏ cặp khoá-giá trị khỏi mảng kết hợp, và cho lại giá trị của phần tử bị xoá.

Chẳng hạn:
%fred = (aaa, bbb, 234.5, 34.56) ; # cho %fred 2 phần tử
delete $fred{aaa};
# %fred bây giờ chỉ còn một cặp khoá-giá trị
Bài tập
Xem phụ lục A về lời giải.
1. Hãy viết một chơng trình đọc và in một xâu và giá trị ánh xạ của nó tơng ứng với
ánh xạ đợc trình bầy trong bảng sau:
Cái vào Cái ra
đỏ
lục
xanh
táo

đại dơng

2. Hãy viết một chơng trình đọc một chuỗi các từ với một từ trên dòng cho tới cuối
tệp, rồi in ra một tóm tắt có bao nhiêu lần mỗi từ đã gặp. (Thêm một thách thức,
hãy sắp xếp các từ theo thứ tự giảm dần mã ASCII khi đa ra.)
6
Vào / ra cơ bản
Vào từ STDIN
Việc đọc từ lối vào chuẩn (qua bộ khiển giải Perl đợc gọi là STDIN) thì thật dễ
dàng. Chúng ta đã làm việc này với toán tử <STDIN>. Việc tính toán tử này trong ngữ
cảnh vô hớng cho bạn một dòng tiếp của cái vào, hay undef nếu không còn dòng nào
nữa, giống nh:
$a = <STDIN>; # đọc dòng tiếp
Việc tính toán tử này trong ngữ cảnh mảng sẽ cho bạn tất cả các dòng còn lại nh
một danh sách - mỗi phần tử của danh sách này là một dòng, bao gồm các kết thúc
dòng mới của nó. Chúng ta đã thấy điều này trớc đây, nhng xem nh việc làm mới lại,

nó có thể trông nh một cái gì đó tựa nh thế này:
@a = <STDIN>;
Một cách điển hình, một trong những điều bạn muốn làm là đọc tất cả các dòng
một lúc, và làm điều gì đó trên mỗi dòng. Một cách chung để làm điều này là:
while ($_ = <STDIN>) {
# xử lí $_ tại đây (cho từng dòng)
}
Cứ mỗi khi một dòng đợc đọc vào, <STDIN> lại cho một giá trị đúng
*
, cho nên
chu trình tiếp tục thực hiện. Khi <STDIN> không còn dòng nào để đọc nữa thì nó cho
lại undef , cho giá trị sai, kết thúc chu trình.
Việc đọc một giá trị vô hớng cho <STDIN> và dùng giá trị đó làm biểu thức điều
khiển cho chu trình (nh trong thí dụ trớc) thờng hay xuáat hiện đến mức Perl có hẳn
một cáhc viết tắt cho nó. Bất kì khi nào việc kiểm thử chu trình chỉ bao gồm một toán
tử đa vào (cái gì đó tựa nh <...>), thì Perl tự động sao dòng đợc đọc vào trong biến $_.
while ($_ = <STDIN>) { # giống while ($_ = <STDIN>)
chop; # giống chop($_)
# các phép toán khác với $_ ở đây
}
*
*
Nếu dòng cuối cùng của tệp chỉ có môt jksi tự 0 thì <STDIN> cho lại undef tại dòng đó; thay vì tại cuối tệp. Nếu
bạn tạo ra một tệp giống nh thế thì ngời lập trình Perl trên toàn thế giới sẽ gửi cho bạn th giận dỗi. Nhng đó là một
tệp bệnh hoạn làm phá vỡ việc dùng loại chu trình này.
Trong chơng này:
Vào từ STDIN
Vào từ toán tử
Diamond
Đa ra STDOUT

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×